Squashed 'third_party/protobuf/' content from commit e35e248

Change-Id: I6cbe123d09fe50fdcad0e51466665daeee7433c7
git-subtree-dir: third_party/protobuf
git-subtree-split: e35e24800fb8d694bdeea5fd63dc7d1b14d68723
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..073673a
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,825 @@
+## 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_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_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_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/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/README.md b/src/README.md
new file mode 100644
index 0000000..4e312c0
--- /dev/null
+++ b/src/README.md
@@ -0,0 +1,209 @@
+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)
+
+On Ubuntu, you can install them with:
+
+  $ sudo apt-get install autoconf automake libtool curl
+
+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.
+
+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/google/protobuf/any.cc b/src/google/protobuf/any.cc
new file mode 100644
index 0000000..f3ca06b
--- /dev/null
+++ b/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) {
+  return string(kTypeGoogleApisComPrefix) + 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) {
+  type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(),
+                        GetTypeUrl(message.GetDescriptor()));
+  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());
+  const string full_name = descriptor->full_name();
+  if (type_url.length() < full_name.length()) {
+      return false;
+  }
+  return (0 == type_url.compare(
+    type_url.length() - full_name.length(),
+    full_name.length(),
+    full_name));
+}
+
+bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) {
+  static const char* prefix[] = {
+    kTypeGoogleApisComPrefix,
+    kTypeGoogleProdComPrefix
+  };
+  for (int i = 0; i < 2; i++) {
+    const int prefix_len = strlen(prefix[i]);
+    if (strncmp(type_url.c_str(), prefix[i], prefix_len) == 0) {
+      full_type_name->assign(type_url.data() + prefix_len,
+                             type_url.size() - prefix_len);
+      return true;
+    }
+  }
+  return false;
+}
+
+
+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/google/protobuf/any.h b/src/google/protobuf/any.h
new file mode 100644
index 0000000..c8dbef1
--- /dev/null
+++ b/src/google/protobuf/any.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_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);
+
+  void PackFrom(const Message& message);
+
+  bool UnpackTo(Message* message) const;
+
+  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/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
new file mode 100644
index 0000000..0bf523b
--- /dev/null
+++ b/src/google/protobuf/any.pb.cc
@@ -0,0 +1,483 @@
+// 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(\014BK\n\023com.google.protobufB\010AnyProtoP\001\240"
+    "\001\001\242\002\003GPB\252\002\036Google.Protobuf.WellKnownType"
+    "sb\006proto3", 169);
+  ::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);
+}
+
+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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Any* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Any>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Any::MergeFrom(const Any& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Any::CopyFrom(const Any& from) {
+  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() {
+  
+  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() {
+  
+  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/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
new file mode 100644
index 0000000..97982ec
--- /dev/null
+++ b/src/google/protobuf/any.pb.h
@@ -0,0 +1,250 @@
+// 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);
+  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() {
+  
+  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() {
+  
+  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/google/protobuf/any.proto b/src/google/protobuf/any.proto
new file mode 100644
index 0000000..e8a18bc
--- /dev/null
+++ b/src/google/protobuf/any.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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+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 message along with a URL
+// that describes the type of the serialized message.
+//
+//
+// 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 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`).
+  // * 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 valid serialized data of the above specified type.
+  bytes value = 2;
+}
diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc
new file mode 100644
index 0000000..1bfaa63
--- /dev/null
+++ b/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/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto
new file mode 100644
index 0000000..0c5b30b
--- /dev/null
+++ b/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/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
new file mode 100644
index 0000000..e589a89
--- /dev/null
+++ b/src/google/protobuf/api.pb.cc
@@ -0,0 +1,1983 @@
+// 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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Api* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Api>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Api::MergeFrom(const Api& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Api::CopyFrom(const Api& from) {
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  ::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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Method*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Method* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Method>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Method::MergeFrom(const Method& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Method::CopyFrom(const Method& from) {
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  root_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool Mixin::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Mixin* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Mixin>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Mixin::MergeFrom(const Mixin& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Mixin::CopyFrom(const Mixin& from) {
+  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() {
+  
+  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() {
+  
+  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/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
new file mode 100644
index 0000000..e1dca4e
--- /dev/null
+++ b/src/google/protobuf/api.pb.h
@@ -0,0 +1,976 @@
+// 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() {
+  
+  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() {
+  
+  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() {
+  
+  ::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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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/google/protobuf/api.proto b/src/google/protobuf/api.proto
new file mode 100644
index 0000000..dbe87b8
--- /dev/null
+++ b/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/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
new file mode 100755
index 0000000..cd0b21a
--- /dev/null
+++ b/src/google/protobuf/arena.cc
@@ -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.
+
+#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;
+}
+
+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/google/protobuf/arena.h b/src/google/protobuf/arena.h
new file mode 100644
index 0000000..5ad94fa
--- /dev/null
+++ b/src/google/protobuf/arena.h
@@ -0,0 +1,915 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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.
+class LIBPROTOBUF_EXPORT Arena {
+ 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;
+
+  // 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/google/protobuf/arena_nc.cc b/src/google/protobuf/arena_nc.cc
new file mode 100644
index 0000000..f2f0842
--- /dev/null
+++ b/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/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
new file mode 100644
index 0000000..87a69b2
--- /dev/null
+++ b/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
+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/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
new file mode 100644
index 0000000..df9c5bd
--- /dev/null
+++ b/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/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
new file mode 100644
index 0000000..690cc70
--- /dev/null
+++ b/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/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
new file mode 100644
index 0000000..6b67f44
--- /dev/null
+++ b/src/google/protobuf/arena_unittest.cc
@@ -0,0 +1,1296 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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, 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/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc
new file mode 100644
index 0000000..cce61d7
--- /dev/null
+++ b/src/google/protobuf/arenastring.cc
@@ -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.
+
+// 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));
+  }
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
new file mode 100755
index 0000000..e2e2f25
--- /dev/null
+++ b/src/google/protobuf/arenastring.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.
+
+#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_;
+  }
+
+  inline ::std::string* MutableNoArena(const ::std::string* default_value) {
+    if (ptr_ == default_value) {
+      CreateInstanceNoArena(default_value);
+    }
+    return ptr_;
+  }
+
+  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);
+    }
+  }
+
+  inline void DestroyNoArena(const ::std::string* default_value) {
+    if (ptr_ != default_value) {
+      delete ptr_;
+    }
+    ptr_ = NULL;
+  }
+
+  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/google/protobuf/arenastring_unittest.cc b/src/google/protobuf/arenastring_unittest.cc
new file mode 100644
index 0000000..3fb582b
--- /dev/null
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -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.
+
+// arenastring_unittest.cc is not open-sourced. Do not include in open-source
+// distribution.
+
+// 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/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
new file mode 100644
index 0000000..473eb4e
--- /dev/null
+++ b/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/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
new file mode 100644
index 0000000..b989f15
--- /dev/null
+++ b/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/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
new file mode 100644
index 0000000..3a816b0
--- /dev/null
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -0,0 +1,1872 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 <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];
+
+  // Iterate through all arguments and parse them.
+  for (int i = 1; i < argc; i++) {
+    string name, value;
+
+    if (ParseArgument(argv[i], &name, &value)) {
+      // Returned true => Use the next argument as the flag value.
+      if (i + 1 == argc || argv[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 = argv[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/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
new file mode 100644
index 0000000..f196ffc
--- /dev/null
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -0,0 +1,393 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
new file mode 100644
index 0000000..dda007d
--- /dev/null
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -0,0 +1,1829 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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, contents, 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/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
new file mode 100644
index 0000000..c3e9fe7
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc
@@ -0,0 +1,158 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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];
+    if (*map_slot != NULL) 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/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc
new file mode 100644
index 0000000..1a11bce
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc
@@ -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.
+
+// 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(set<string>* enum_names) {
+  if (!options_.proto_h) {
+    return;
+  }
+  enum_names->insert(classname_);
+}
+
+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->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_ + "_";
+
+    if (i > 0) printer->Print(",\n");
+    printer->Print(vars, "$prefix$$name$ = $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())) {
+    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())) {
+    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_;
+  printer->Print(vars, "typedef $classname$ $nested_name$;\n");
+
+  for (int j = 0; j < descriptor_->value_count(); j++) {
+    vars["tag"] = EnumValueName(descriptor_->value(j));
+    printer->Print(vars,
+      "static const $nested_name$ $tag$ = $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())) {
+    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_;
+
+  if (HasDescriptorMethods(descriptor_->file())) {
+    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,
+        "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/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h
new file mode 100644
index 0000000..f3aa72e
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_enum.h
@@ -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.
+
+// 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 <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.
+  explicit 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.
+  void FillForwardDeclaration(set<string>* 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_;
+  string classname_;
+  Options options_;
+  // whether to generate the *_ARRAYSIZE constant.
+  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/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc
new file mode 100644
index 0000000..824e220
--- /dev/null
+++ b/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>
+
+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)
+  : 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_,
+    "$type$ $name$() const$deprecation$;\n"
+    "void set_$name$($type$ value)$deprecation$;\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())) {
+      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(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)
+  : 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())) {
+    printer->Print(variables_,
+      "mutable int _$name$_cached_byte_size_;\n");
+  }
+}
+
+void RepeatedEnumFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$type$ $name$(int index) const$deprecation$;\n"
+    "void set_$name$(int index, $type$ value)$deprecation$;\n"
+    "void add_$name$($type$ value)$deprecation$;\n");
+  printer->Print(variables_,
+    "const ::google::protobuf::RepeatedField<int>& $name$() const$deprecation$;\n"
+    "::google::protobuf::RepeatedField<int>* mutable_$name$()$deprecation$;\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())) {
+      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())) {
+      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())) {
+        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/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h
new file mode 100644
index 0000000..5b1d01e
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.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.
+
+// 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:
+  explicit 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:
+  explicit 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:
+  explicit 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/google/protobuf/compiler/cpp/cpp_extension.cc b/src/google/protobuf/compiler/cpp/cpp_extension.cc
new file mode 100644
index 0000000..c42f162
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_extension.h b/src/google/protobuf/compiler/cpp/cpp_extension.h
new file mode 100644
index 0000000..1c1caf1
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc
new file mode 100644
index 0000000..8d47d4e
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_field.cc
@@ -0,0 +1,198 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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)["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),
+      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/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h
new file mode 100644
index 0000000..1d7f823
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_field.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)
+//  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:
+  FieldGenerator() {}
+  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;
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+  explicit FieldGeneratorMap(const Descriptor* descriptor, const Options& options);
+  ~FieldGeneratorMap();
+
+  const FieldGenerator& get(const FieldDescriptor* field) const;
+
+ private:
+  const Descriptor* descriptor_;
+  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/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc
new file mode 100644
index 0000000..37e4bae
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_file.cc
@@ -0,0 +1,1043 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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),
+      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()]),
+      options_(options) {
+
+  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) {
+  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);
+  }
+
+  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) {
+  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);
+
+  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) {
+  bool well_known = 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", well_known ? "<" : "\"",
+    "right", well_known ? ">" : "\"");
+
+  // Unknown fields implementation in lite mode uses StringOutputStream
+  if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) {
+    printer->Print(
+      "#include <google/protobuf/io/zero_copy_stream_impl_lite.h>\n");
+  }
+
+  if (HasDescriptorMethods(file_)) {
+    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_)) {
+    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_)) {
+      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_)) {
+      printer->Print(
+          "\n"
+          "namespace {\n"
+          "\n"
+          "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n"
+          "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_)) {
+    // 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;
+  }
+
+  set<string>& classes() { return classes_; }
+  set<string>& enums() { return enums_; }
+
+  void Print(io::Printer* printer) const {
+    for (set<string>::const_iterator it = enums_.begin(), end = enums_.end();
+         it != end; ++it) {
+      printer->Print("enum $enumname$ : int;\n"
+                     "bool $enumname$_IsValid(int value);\n",
+                     "enumname", it->c_str());
+    }
+    for (set<string>::const_iterator it = classes_.begin(),
+                                     end = classes_.end();
+         it != end; ++it) {
+      printer->Print("class $classname$;\n", "classname", it->c_str());
+    }
+    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_;
+  set<string> classes_;
+  set<string> 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_)) {
+    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_)) {
+      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_, 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_)) {
+    // 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_, 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"
+    "\n",
+    "filename", file_->name(),
+    "filename_identifier", filename_identifier);
+}
+
+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_)) {
+    printer->Print(
+      "#include <google/protobuf/metadata.h>\n");
+  }
+  if (file_->message_type_count() > 0) {
+    if (HasDescriptorMethods(file_)) {
+      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_)) {
+      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_)) {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_reflection.h>\n");
+    } else {
+      printer->Print(
+          "#include <google/protobuf/generated_enum_util.h>\n");
+    }
+  }
+
+  if (HasGenericServices(file_)) {
+    printer->Print(
+      "#include <google/protobuf/service.h>\n");
+  }
+
+  if (UseUnknownFieldSet(file_) && 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::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++) {
+    bool well_known = 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", well_known ? "<" : "\"",
+      "right", well_known ? ">" : "\"");
+  }
+}
+
+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) {
+  set<string> classes;
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->FillMessageForwardDeclarations(&classes);
+  }
+  for (set<string>::const_iterator it = classes.begin(), end = classes.end();
+       it != end; ++it) {
+    printer->Print("class $classname$;\n", "classname", it->c_str());
+  }
+}
+
+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_)) {
+    // 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/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h
new file mode 100644
index 0000000..29cdaea
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_file.h
@@ -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.
+
+// 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.
+  explicit FileGenerator(const FileDescriptor* file,
+                         const Options& options);
+  ~FileGenerator();
+
+  void GenerateProtoHeader(io::Printer* printer);
+  void GeneratePBHeader(io::Printer* printer);
+  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);
+
+  // 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_;
+
+  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_;
+  const Options options_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc
new file mode 100644
index 0000000..781526b
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.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.
+
+// 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 {
+      *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"));
+    io::Printer printer(output.get(), '$');
+    file_generator.GenerateProtoHeader(&printer);
+  }
+
+  basename.append(".pb");
+  {
+    google::protobuf::scoped_ptr<io::ZeroCopyOutputStream> output(
+        generator_context->Open(basename + ".h"));
+    io::Printer printer(output.get(), '$');
+    file_generator.GeneratePBHeader(&printer);
+  }
+
+  // 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/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h
new file mode 100644
index 0000000..3d517cf
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
new file mode 100644
index 0000000..fb46e38
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -0,0 +1,699 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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", "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) {
+  return HasDescriptorMethods(descriptor->file()) ?
+      "::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) {
+  if (HasDescriptorMethods(file) || 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, 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, printer, with_static_init, without_static_init);
+}
+
+void PrintHandlingOptionalStaticInitializers(
+    const map<string, string>& vars, const FileDescriptor* file,
+    io::Printer* printer, const char* with_static_init,
+    const char* without_static_init) {
+  if (StaticInitializersForced(file)) {
+    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) {
+  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+    return STRICT;
+  } else if (field->file()->options().optimize_for() !=
+             FileOptions::LITE_RUNTIME) {
+    return VERIFY;
+  } else {
+    return NONE;
+  }
+}
+
+static void GenerateUtf8CheckCode(const FieldDescriptor* field,
+                                  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)) {
+    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,
+                                    bool for_parse,
+                                    const map<string, string>& variables,
+                                    const char* parameters,
+                                    io::Printer* printer) {
+  GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+                        "VerifyUtf8String", "VerifyUTF8StringNamedField",
+                        printer);
+}
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+                                  bool for_parse,
+                                  const map<string, string>& variables,
+                                  const char* parameters,
+                                  io::Printer* printer) {
+  GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+                        "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
+                        printer);
+}
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
new file mode 100644
index 0000000..a22d414
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -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.
+
+// 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/descriptor.h>
+#include <google/protobuf/descriptor.pb.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);
+
+// 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.
+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;
+}
+
+// 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) {
+  return file->options().optimize_for() != 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) {
+  return file->options().optimize_for() != FileOptions::CODE_SIZE;
+}
+
+// Do message classes in this file have descriptor and reflection methods?
+inline bool HasDescriptorMethods(const FileDescriptor* file) {
+  return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor* file) {
+  return file->service_count() > 0 &&
+         file->options().optimize_for() != 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) {
+  return file->options().optimize_for() == FileOptions::SPEED;
+}
+
+// Returns whether we have to generate code with static initializers.
+bool StaticInitializersForced(const FileDescriptor* file);
+
+// 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, 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,
+    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,
+    bool for_parse,
+    const map<string, string>& variables,
+    const char* parameters,
+    io::Printer* printer);
+
+void GenerateUtf8CheckCodeForCord(
+    const FieldDescriptor* field,
+    bool for_parse,
+    const map<string, string>& variables,
+    const char* parameters,
+    io::Printer* printer);
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
new file mode 100644
index 0000000..e5e2f07
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -0,0 +1,410 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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()) ?
+       "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())) {
+    (*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)
+    : 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_,
+      "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n"
+      "    $name$() const$deprecation$;\n"
+      "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n"
+      "    mutable_$name$()$deprecation$;\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())) {
+    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())) {
+      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, true, variables_,
+        "entry->key().data(), entry->key().length(),\n", printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        value_field, 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, false, variables_,
+        "it->first.data(), it->first.length(),\n", printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        value_field, 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, false, variables_,
+        "it->first.data(), it->first.length(),\n", printer);
+  }
+  if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+    GenerateUtf8CheckCodeForString(
+        value_field, 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/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h
new file mode 100644
index 0000000..5e20562
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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:
+  explicit 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/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
new file mode 100644
index 0000000..8304ebb
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -0,0 +1,3765 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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) {
+  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,
+    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)) {
+      if (HasRequiredFields(field->message_type(), already_seen)) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+static bool HasRequiredFields(const Descriptor* type) {
+  hash_set<const Descriptor*> already_seen;
+  return HasRequiredFields(type, &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(set<string>* class_names) {
+  class_names->insert(classname_);
+
+  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(set<string>* 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, "void clear_$name$()$deprecation$;\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, "int $name$_size() const$deprecation$;\n");
+    } else if (HasHasMethod(field)) {
+      printer->Print(vars, "bool has_$name$() const$deprecation$;\n");
+    } else if (HasPrivateHasMethod(field)) {
+      printer->Print(vars,
+          "private:\n"
+          "bool has_$name$() const$deprecation$;\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, "void clear_$name$()$deprecation$;\n");
+    }
+    printer->Print(vars, "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_);
+
+  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_);
+  }
+  printer->Print(vars,
+    "class $dllexport$$classname$ : public $superclass$ {\n");
+  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())) {
+      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()) &&
+      !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())) {
+    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"
+      "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,
+    "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())) {
+    if (HasDescriptorMethods(descriptor_->file())) {
+      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())) {
+      printer->Print(
+        "void DiscardUnknownFields();\n");
+    }
+    if (HasFastArraySerialization(descriptor_->file())) {
+      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())) {
+    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())) {
+    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())) {
+    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()) &&
+      !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())) {
+    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(), 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())) {
+    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())) {
+    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())) {
+    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())) {
+    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 (!UseUnknownFieldSet(descriptor_->file())) {
+    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"
+      "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())) {
+    GenerateClear(printer);
+    printer->Print("\n");
+
+    GenerateMergeFromCodedStream(printer);
+    printer->Print("\n");
+
+    GenerateSerializeWithCachedSizes(printer);
+    printer->Print("\n");
+
+    if (HasFastArraySerialization(descriptor_->file())) {
+      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())) {
+    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(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())) {
+    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())) {
+    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(), 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_);
+  }
+  string initializer_with_arena = superclass + "()";
+
+  if (descriptor_->extension_range_count() > 0) {
+    initializer_with_arena += ",\n  _extensions_(arena)";
+  }
+
+  if (UseUnknownFieldSet(descriptor_->file())) {
+    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()) ?
+    ", _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()))) {
+      string name;
+      if (field->containing_oneof()) {
+        name = classname_ + "_default_oneof_instance_->";
+      }
+      name += FieldName(field);
+      PrintHandlingOptionalStaticInitializers(
+        descriptor_->file(), 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())) {
+      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())) {
+    printer->Print(
+        ",\n    _internal_metadata_(NULL)");
+  } else if (!UseUnknownFieldSet(descriptor_->file())) {
+    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()) &&
+      !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(), 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",
+                 "classname", classname_);
+  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 =
+      "#define ZR_HELPER_(f) reinterpret_cast<char*>(\\\n"
+      "  &reinterpret_cast<$classname$*>(16)->f)\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())) {
+      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();
+    string message_class;
+
+    printer->Print(oneof_vars,
+        "void $classname$::clear_$oneofname$() {\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(
+        "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())) {
+    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));
+      }
+    }
+
+    if (PreserveUnknownFields(descriptor_)) {
+      if (UseUnknownFieldSet(descriptor_->file())) {
+        printer->Print(
+          "_internal_metadata_.Swap(&other->_internal_metadata_);\n");
+      } else {
+        printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n");
+      }
+    } else {
+      // Still swap internal_metadata as it may contain more than just
+      // unknown fields.
+      printer->Print(
+        "_internal_metadata_.Swap(&other->_internal_metadata_);\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())) {
+    // 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"
+      "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+      "classname", classname_);
+    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"
+      "  ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n"
+      "} else {\n"
+      "  MergeFrom(*source);\n"
+      "}\n",
+      "classname", classname_);
+
+    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"
+    "  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n",
+    "classname", classname_);
+  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())) {
+      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())) {
+    // 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",
+      "classname", classname_);
+    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",
+    "classname", classname_);
+  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(), 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 (!(EXPRESSION)) goto failure\n"
+    "  ::google::protobuf::uint32 tag;\n",
+    "classname", classname_);
+
+  if (!UseUnknownFieldSet(descriptor_->file())) {
+    // 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())) {
+        PrintHandlingOptionalStaticInitializers(
+          descriptor_->file(), 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(), 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(), 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())) {
+      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()));
+    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()));
+    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())) {
+      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"
+      "  int total_size = _extensions_.MessageSetByteSize();\n",
+      "classname", classname_);
+    GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file()));
+    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",
+        "classname", classname_);
+    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",
+    "classname", classname_);
+  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())) {
+      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) &&
+        HasRequiredFields(field->message_type())) {
+      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/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h
new file mode 100644
index 0000000..8e19a3f
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_message.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.
+
+// 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.
+  void FillMessageForwardDeclarations(set<string>* class_names);
+  void FillEnumForwardDeclarations(set<string>* 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/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
new file mode 100644
index 0000000..b454589
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc
@@ -0,0 +1,1045 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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()) ?
+       "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)
+  : 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_,
+      "const $type$& $name$() const$deprecation$;\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_,
+    "$type$* mutable_$name$()$deprecation$;\n"
+    "$type$* $release_name$()$deprecation$;\n"
+    "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+}
+
+void MessageFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+       "private:\n"
+       "void _slow_mutable_$name$()$deprecation$;\n");
+    if (SupportsArenas(descriptor_->message_type())) {
+      printer->Print(variables_,
+       "void _slow_set_allocated_$name$(\n"
+       "    ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n");
+    }
+    printer->Print(variables_,
+       "$type$* _slow_$release_name$()$deprecation$;\n"
+       "public:\n");
+  }
+  GenerateGetterDeclaration(printer);
+  if (!dependent_field_) {
+    printer->Print(variables_,
+      "$type$* mutable_$name$()$deprecation$;\n"
+      "$type$* $release_name$()$deprecation$;\n"
+      "void set_allocated_$name$($type$* $name$)$deprecation$;\n");
+  }
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "$type$* unsafe_arena_release_$name$()$deprecation$;\n"
+      "void unsafe_arena_set_allocated_$name$(\n"
+      "    $type$* $name$)$deprecation$;\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"
+      "  $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"
+      "  $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"
+      "  $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(), 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"
+      "  $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"
+      "  $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_,
+      "const $type$& $name$() const$deprecation$;\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_,
+      "const $type$& $name$() const$deprecation$;\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"
+      "  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"
+      "  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"
+      "  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)
+  : 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_,
+    "$type$* mutable_$name$(int index)$deprecation$;\n"
+    "$type$* add_$name$()$deprecation$;\n");
+  if (dependent_getter_) {
+    printer->Print(variables_,
+      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "    $name$() const$deprecation$;\n");
+  }
+  printer->Print(variables_,
+    "::google::protobuf::RepeatedPtrField< $type$ >*\n"
+    "    mutable_$name$()$deprecation$;\n");
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateDependentAccessorDeclarations(io::Printer* printer) const {
+  if (dependent_getter_) {
+    printer->Print(variables_,
+      "const $type$& $name$(int index) const$deprecation$;\n");
+  }
+  if (dependent_field_) {
+    InternalGenerateTypeDependentAccessorDeclarations(printer);
+  }
+}
+
+void RepeatedMessageFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  if (!dependent_getter_) {
+    printer->Print(variables_,
+      "const $type$& $name$(int index) const$deprecation$;\n");
+  }
+  if (!dependent_field_) {
+    InternalGenerateTypeDependentAccessorDeclarations(printer);
+  }
+  if (!dependent_getter_) {
+    printer->Print(variables_,
+      "const ::google::protobuf::RepeatedPtrField< $type$ >&\n"
+      "    $name$() const$deprecation$;\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/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h
new file mode 100644
index 0000000..35efd0f
--- /dev/null
+++ b/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:
+  explicit 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:
+  explicit 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:
+  explicit 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/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h
new file mode 100644
index 0000000..4463f20
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_options.h
@@ -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: 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) {
+  }
+  string dllexport_decl;
+  bool safe_boundary_check;
+  bool proto_h;
+};
+
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
new file mode 100644
index 0000000..d1efbfe
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc
@@ -0,0 +1,251 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.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/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc
new file mode 100644
index 0000000..9f929d3
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.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)
+//  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)
+  : 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_,
+    "$type$ $name$() const$deprecation$;\n"
+    "void set_$name$($type$ value)$deprecation$;\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)
+  : 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())) {
+    printer->Print(variables_,
+      "mutable int _$name$_cached_byte_size_;\n");
+  }
+}
+
+void RepeatedPrimitiveFieldGenerator::
+GenerateAccessorDeclarations(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$type$ $name$(int index) const$deprecation$;\n"
+    "void set_$name$(int index, $type$ value)$deprecation$;\n"
+    "void add_$name$($type$ value)$deprecation$;\n");
+  printer->Print(variables_,
+    "const ::google::protobuf::RepeatedField< $type$ >&\n"
+    "    $name$() const$deprecation$;\n"
+    "::google::protobuf::RepeatedField< $type$ >*\n"
+    "    mutable_$name$()$deprecation$;\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/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h
new file mode 100644
index 0000000..fcd7d68
--- /dev/null
+++ b/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:
+  explicit 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:
+  explicit 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:
+  explicit 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/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc
new file mode 100644
index 0000000..226c2aa
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h
new file mode 100644
index 0000000..ede2fd8
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
new file mode 100644
index 0000000..6b0821a
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -0,0 +1,864 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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)
+  : 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_,
+    "const ::std::string& $name$() const$deprecation$;\n"
+    "void set_$name$(const ::std::string& value)$deprecation$;\n"
+    "void set_$name$(const char* value)$deprecation$;\n"
+    "void set_$name$(const $pointer_type$* value, size_t size)"
+                 "$deprecation$;\n"
+    "::std::string* mutable_$name$()$deprecation$;\n"
+    "::std::string* $release_name$()$deprecation$;\n"
+    "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n");
+  if (SupportsArenas(descriptor_)) {
+    printer->Print(variables_,
+      "::std::string* unsafe_arena_release_$name$()$deprecation$;\n"
+      "void unsafe_arena_set_allocated_$name$(\n"
+      "    ::std::string* $name$)$deprecation$;\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"
+      "  $clear_hasbit$\n"
+      "  return $name$_.Release($default_variable$, GetArenaNoVirtual());\n"
+      "}\n"
+      "$inline$ ::std::string* $classname$::unsafe_arena_release_$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_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"
+      "  $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_, 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_, 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_, 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"
+      "  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"
+      "  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_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"
+      "  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_, true, variables_,
+        "this->$name$().data(), this->$name$().length(),\n", printer);
+  }
+}
+
+
+// ===================================================================
+
+RepeatedStringFieldGenerator::
+RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
+                             const Options& 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_,
+    "const ::std::string& $name$(int index) const$deprecation$;\n"
+    "::std::string* mutable_$name$(int index)$deprecation$;\n"
+    "void set_$name$(int index, const ::std::string& value)$deprecation$;\n"
+    "void set_$name$(int index, const char* value)$deprecation$;\n"
+    ""
+    "void set_$name$(int index, const $pointer_type$* value, size_t size)"
+                 "$deprecation$;\n"
+    "::std::string* add_$name$()$deprecation$;\n"
+    "void add_$name$(const ::std::string& value)$deprecation$;\n"
+    "void add_$name$(const char* value)$deprecation$;\n"
+    "void add_$name$(const $pointer_type$* value, size_t size)"
+                 "$deprecation$;\n");
+
+  printer->Print(variables_,
+    "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const"
+                 "$deprecation$;\n"
+    "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()"
+                 "$deprecation$;\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"
+    "  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_, 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_, 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_, 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/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h
new file mode 100644
index 0000000..616e206
--- /dev/null
+++ b/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:
+  explicit 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:
+  explicit 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:
+  explicit 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/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto
new file mode 100644
index 0000000..4e25b2e
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto
new file mode 100644
index 0000000..cb6ca1b
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
new file mode 100644
index 0000000..9942a34
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -0,0 +1,2140 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 {
+using internal::NewPermanentCallback;
+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_(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/google/protobuf/compiler/cpp/cpp_unittest.h b/src/google/protobuf/compiler/cpp/cpp_unittest.h
new file mode 100644
index 0000000..69c8f44
--- /dev/null
+++ b/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/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
new file mode 100644
index 0000000..422eb73
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/metadata_test.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.
+
+#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/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace cpp {
+namespace {
+
+}  // namespace
+}  // namespace cpp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
new file mode 100644
index 0000000..587e022
--- /dev/null
+++ b/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/google/protobuf/compiler/csharp/csharp_doc_comment.h b/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
new file mode 100644
index 0000000..75eb0ea
--- /dev/null
+++ b/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/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
new file mode 100644
index 0000000..5668198
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -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.
+
+#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>
+
+using google::protobuf::internal::scoped_ptr;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) :
+    SourceGeneratorBase(descriptor->file()),
+    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();
+  for (int i = 0; i < descriptor_->value_count(); i++) {
+      WriteEnumValueDocComment(printer, descriptor_->value(i));
+      printer->Print("$name$ = $number$,\n",
+                   "name", descriptor_->value(i)->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/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h
new file mode 100644
index 0000000..2cf2fad
--- /dev/null
+++ b/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);
+  ~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/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
new file mode 100644
index 0000000..d38fb1e
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -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.
+
+#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_enum_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor,
+                                       int fieldOrdinal)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+}
+
+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)
+  : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) {
+}
+
+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/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
new file mode 100644
index 0000000..0836415
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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);
+  ~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);
+  ~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/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
new file mode 100644
index 0000000..5df43d3
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -0,0 +1,425 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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)
+    : SourceGeneratorBase(descriptor->file()),
+      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:
+      return type_name() + "." + descriptor->default_value_enum()->name();
+    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/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
new file mode 100644
index 0000000..d83543b
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.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_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);
+  ~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/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc
new file mode 100644
index 0000000..825de54
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -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.
+
+#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_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) {
+  ReflectionClassGenerator reflectionClassGenerator(file);
+  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;
+  }
+
+  std::string file_extension = ".cs";
+  std::string base_namespace = "";
+  bool generate_directories = false;
+  for (int i = 0; i < options.size(); i++) {
+    if (options[i].first == "file_extension") {
+      file_extension = options[i].second;
+    } else if (options[i].first == "base_namespace") {
+      base_namespace = options[i].second;
+      generate_directories = true;
+    } else {
+      *error = "Unknown generator option: " + options[i].first;
+      return false;
+    }
+  }
+
+  string filename_error = "";
+  std::string filename = GetOutputFile(file, file_extension, generate_directories, 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);
+
+  return true;
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h
new file mode 100644
index 0000000..9b54e91
--- /dev/null
+++ b/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/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
new file mode 100644
index 0000000..7ef7df4
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -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.
+
+#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 csharp {
+namespace {
+
+// TODO(jtattermusch): add some tests.
+
+}  // namespace
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
new file mode 100644
index 0000000..c51fe44
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -0,0 +1,405 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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_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);
+}
+
+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) {
+  switch (descriptor->type()) {
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      if (descriptor->is_repeated()) {
+        if (descriptor->is_map()) {
+          return new MapFieldGenerator(descriptor, fieldOrdinal);
+        } else {
+          return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal);
+        }
+      } else {
+        if (IsWrapperType(descriptor)) {
+          if (descriptor->containing_oneof()) {
+            return new WrapperOneofFieldGenerator(descriptor, fieldOrdinal);
+          } else {
+            return new WrapperFieldGenerator(descriptor, fieldOrdinal);
+          }
+        } else {
+          if (descriptor->containing_oneof()) {
+            return new MessageOneofFieldGenerator(descriptor, fieldOrdinal);
+          } else {
+            return new MessageFieldGenerator(descriptor, fieldOrdinal);
+          }
+        }
+      }
+    case FieldDescriptor::TYPE_ENUM:
+      if (descriptor->is_repeated()) {
+        return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal);
+      } else {
+        if (descriptor->containing_oneof()) {
+          return new EnumOneofFieldGenerator(descriptor, fieldOrdinal);
+        } else {
+          return new EnumFieldGenerator(descriptor, fieldOrdinal);
+        }
+      }
+    default:
+      if (descriptor->is_repeated()) {
+        return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal);
+      } else {
+        if (descriptor->containing_oneof()) {
+          return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal);
+        } else {
+          return new PrimitiveFieldGenerator(descriptor, fieldOrdinal);
+        }
+      }
+  }
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
new file mode 100644
index 0000000..e96e793
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.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)
+//  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/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 {
+
+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);
+
+// 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);
+
+// 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/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
new file mode 100644
index 0000000..15c68b3
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -0,0 +1,138 @@
+// 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)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+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));  
+  scoped_ptr<FieldGeneratorBase> value_generator(CreateFieldGenerator(value_descriptor, 2));
+
+  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/google/protobuf/compiler/csharp/csharp_map_field.h b/src/google/protobuf/compiler/csharp/csharp_map_field.h
new file mode 100644
index 0000000..f33fe1c
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_map_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_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);
+  ~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/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
new file mode 100644
index 0000000..e0230a2
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -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.
+
+#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)
+    : SourceGeneratorBase(descriptor->file()),
+      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));
+      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));
+        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));
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
new file mode 100644
index 0000000..f0c49ac
--- /dev/null
+++ b/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);
+  ~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/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
new file mode 100644
index 0000000..f81f769
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.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 <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>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor,
+                                             int fieldOrdinal)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+  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)
+    : MessageFieldGenerator(descriptor, fieldOrdinal) {
+  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/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
new file mode 100644
index 0000000..dc6e4dc
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.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_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);
+  ~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);
+  ~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/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/csharp_names.h
new file mode 100644
index 0000000..3080518
--- /dev/null
+++ b/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/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
new file mode 100644
index 0000000..60afd89
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -0,0 +1,217 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_primitive_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor, int fieldOrdinal)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+  // 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)
+    : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
+  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/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
new file mode 100644
index 0000000..8b87ebc
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.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.
+
+#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 {
+
+class PrimitiveFieldGenerator : public FieldGeneratorBase {
+ public:
+  PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  ~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);
+  ~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/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
new file mode 100644
index 0000000..22dae43
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -0,0 +1,291 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_reflection_class.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+ReflectionClassGenerator::ReflectionClassGenerator(const FileDescriptor* file)
+    : SourceGeneratorBase(file),
+      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));
+      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));
+      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/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
new file mode 100644
index 0000000..0a5b8ed
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.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_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);
+  ~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/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
new file mode 100644
index 0000000..3a11b75
--- /dev/null
+++ b/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)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+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/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
new file mode 100644
index 0000000..ee50eef
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_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_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);
+  ~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/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
new file mode 100644
index 0000000..fc12fae
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -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.
+
+#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)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+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_));
+    single_generator->GenerateCodecCode(printer);
+  } else {
+    scoped_ptr<FieldGeneratorBase> single_generator(new MessageFieldGenerator(descriptor_, fieldOrdinal_));
+    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/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
new file mode 100644
index 0000000..cf601c7
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_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_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 {
+
+class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
+ public:
+  RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  ~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/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
new file mode 100644
index 0000000..5fe0b20
--- /dev/null
+++ b/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)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+}
+
+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/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
new file mode 100644
index 0000000..f1ceeb5
--- /dev/null
+++ b/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);
+  ~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/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
new file mode 100644
index 0000000..735d164
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -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.
+
+#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>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor)
+    : descriptor_(descriptor) {
+}
+
+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_) ? "internal" : "public";  // public_classes is always on.
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
new file mode 100644
index 0000000..6caef17
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.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_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 {
+
+class SourceGeneratorBase {
+ protected:
+  SourceGeneratorBase(const FileDescriptor* descriptor);
+  virtual ~SourceGeneratorBase();
+
+  std::string class_access_level();
+
+  void WriteGeneratedCodeAttributes(io::Printer* printer);
+
+ private:
+  const FileDescriptor* descriptor_;
+
+  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/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
new file mode 100644
index 0000000..6a3750e
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.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.
+
+#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_wrapper_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+WrapperFieldGenerator::WrapperFieldGenerator(const FieldDescriptor* descriptor,
+                                       int fieldOrdinal)
+    : FieldGeneratorBase(descriptor, fieldOrdinal) {
+  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)
+    : WrapperFieldGenerator(descriptor, fieldOrdinal) {
+    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/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
new file mode 100644
index 0000000..6e2414a
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.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.
+
+#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 {
+
+class WrapperFieldGenerator : public FieldGeneratorBase {
+ public:
+  WrapperFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
+  ~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);
+  ~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/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
new file mode 100644
index 0000000..0d9093c
--- /dev/null
+++ b/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/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h
new file mode 100644
index 0000000..cc8fcc3
--- /dev/null
+++ b/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/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
new file mode 100644
index 0000000..be19aa2
--- /dev/null
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -0,0 +1,522 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/compiler/importer.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+
+#include <google/protobuf/stubs/map_util.h>
+#include <google/protobuf/stubs/logging.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/testing/file.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 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/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc
new file mode 100644
index 0000000..7d21fe6
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_context.cc
@@ -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.
+
+#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) {
+  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;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h
new file mode 100644
index 0000000..5b595d0
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_context.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_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;
+  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;
+
+ 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_;
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
+};
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc
new file mode 100644
index 0000000..663f0c9
--- /dev/null
+++ b/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(
+        " *\n"
+        " * <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");
+  }
+}
+
+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"
+    " * Protobuf type {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(message->full_name()));
+  WriteDocCommentBody(printer, message);
+  printer->Print(" */\n");
+}
+
+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 use the field declaration as the first line of the comment, e.g.:
+  //   optional string foo = 5;
+  // This communicates a lot of information about the field in a small space.
+  // If the field is a group, the debug string might end with {.
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(field->DebugString())));
+  WriteDocCommentBody(printer, field);
+  printer->Print(" */\n");
+}
+
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+  printer->Print(
+    "/**\n"
+    " * Protobuf enum {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(enum_->full_name()));
+  WriteDocCommentBody(printer, enum_);
+  printer->Print(" */\n");
+}
+
+void WriteEnumValueDocComment(io::Printer* printer,
+                              const EnumValueDescriptor* value) {
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(value->DebugString())));
+  WriteDocCommentBody(printer, value);
+  printer->Print(" */\n");
+}
+
+void WriteServiceDocComment(io::Printer* printer,
+                            const ServiceDescriptor* service) {
+  printer->Print(
+    "/**\n"
+    " * Protobuf service {@code $fullname$}\n",
+    "fullname", EscapeJavadoc(service->full_name()));
+  WriteDocCommentBody(printer, service);
+  printer->Print(" */\n");
+}
+
+void WriteMethodDocComment(io::Printer* printer,
+                           const MethodDescriptor* method) {
+  printer->Print(
+    "/**\n"
+    " * <code>$def$</code>\n",
+    "def", EscapeJavadoc(FirstLineOf(method->DebugString())));
+  WriteDocCommentBody(printer, method);
+  printer->Print(" */\n");
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_doc_comment.h b/src/google/protobuf/compiler/java/java_doc_comment.h
new file mode 100644
index 0000000..7d9535c
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc
new file mode 100644
index 0000000..ae582ea
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc
new file mode 100644
index 0000000..5fc9b00
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum.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 <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),
+    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();
+
+  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");
+    }
+    printer->Print(vars,
+      "$name$($index$, $number$),\n");
+  }
+
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    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())) {
+    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"
+    "public static $classname$ valueOf(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$.valueOf(number);\n"
+    "        }\n"
+    "      };\n"
+    "\n",
+    "classname", descriptor_->name());
+
+  // -----------------------------------------------------------------
+  // Reflection
+
+  if (HasDescriptorMethods(descriptor_)) {
+    printer->Print(
+      "public final com.google.protobuf.Descriptors.EnumValueDescriptor\n"
+      "    getValueDescriptor() {\n"
+      "  return getDescriptor().getValues().get(index);\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");
+
+    // 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 (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");
+
+    printer->Print("private final int index;\n");
+  }
+
+  // -----------------------------------------------------------------
+
+  printer->Print(
+    "private final int value;\n\n"
+    "private $classname$(int index, int value) {\n",
+    "classname", descriptor_->name());
+  if (HasDescriptorMethods(descriptor_)) {
+    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/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h
new file mode 100644
index 0000000..a0d91f5
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc
new file mode 100644
index 0000000..558da96
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field.cc
@@ -0,0 +1,969 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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());
+  if (descriptor->is_packed()) {
+    (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag(
+        descriptor->number(),
+        internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+  } else {
+    (*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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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$.valueOf($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$.valueOf($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$.valueOf(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$.valueOf((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$.valueOf((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$.valueOf(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$.valueOf(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() &&
+      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$.valueOf(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/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h
new file mode 100644
index 0000000..b8ff734
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
new file mode 100644
index 0000000..e3e87c5
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc
@@ -0,0 +1,966 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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);
+
+    // 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$.valueOf($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(int 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::
+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 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$.valueOf(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$.valueOf((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::
+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 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$.valueOf(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$.valueOf(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() &&
+      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$_ = newIntList($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::
+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"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\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
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "if (!$is_mutable$) {\n"
+      "  $name$_ = newIntList();\n"
+      "}\n"
+      "$name$_.addInt(rawValue);\n");
+  } else {
+    printer->Print(variables_,
+      "int rawValue = input.readEnum();\n"
+      "$type$ value = $type$.valueOf(rawValue);\n"
+        "if (value == null) {\n");
+    if (PreserveUnknownFields(descriptor_->containing_type())) {
+      printer->Print(variables_,
+        "  super.mergeVarintField($number$, rawValue);\n");
+    }
+    printer->Print(variables_,
+      "} else {\n"
+      "  if (!$is_mutable$) {\n"
+      "    $name$_ = newIntList();\n"
+      "  }\n"
+      "  $name$_.addInt(rawValue);\n"
+      "}\n");
+  }
+}
+
+void RepeatedImmutableEnumFieldLiteGenerator::
+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 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/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h
new file mode 100644
index 0000000..2c41c3e
--- /dev/null
+++ b/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 GenerateMergingCode(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 GenerateMergingCode(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 GenerateMergingCode(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/google/protobuf/compiler/java/java_enum_lite.cc b/src/google/protobuf/compiler/java/java_enum_lite.cc
new file mode 100644
index 0000000..ed415ee
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_enum_lite.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 <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"
+    "public static $classname$ valueOf(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$.valueOf(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/google/protobuf/compiler/java/java_enum_lite.h b/src/google/protobuf/compiler/java/java_enum_lite.h
new file mode 100644
index 0000000..ee2f5f7
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
new file mode 100644
index 0000000..4db7085
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_extension.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.
+
+// 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 (HasDescriptorMethods(descriptor_->file())) {
+    // Non-lite extensions
+    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");
+    }
+  } else {
+    // Lite extensions
+    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 ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
+    io::Printer* printer) {
+  int bytecode_estimate = 0;
+  if (descriptor_->extension_scope() == NULL &&
+      HasDescriptorMethods(descriptor_->file())) {
+    // Only applies to non-nested, non-lite 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/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
new file mode 100644
index 0000000..bdd4226
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_extension_lite.cc b/src/google/protobuf/compiler/java/java_extension_lite.cc
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_extension_lite.cc
diff --git a/src/google/protobuf/compiler/java/java_extension_lite.h b/src/google/protobuf/compiler/java/java_extension_lite.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_extension_lite.h
diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc
new file mode 100644
index 0000000..c543476
--- /dev/null
+++ b/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)) {
+            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)) {
+            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)) {
+            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)) {
+            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)) {
+            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)) {
+            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/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h
new file mode 100644
index 0000000..0e24da2
--- /dev/null
+++ b/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 GenerateMergingCode(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/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
new file mode 100644
index 0000000..c817233
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -0,0 +1,607 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 = 1<<15;  // aka 32K
+
+  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)
+    : 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);
+  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_) ? "" : "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_)) {
+        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_)) {
+      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.
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_[i]->GenerateStaticVariables(printer);
+  }
+
+  printer->Print("\n");
+
+  if (HasDescriptorMethods(file_)) {
+    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 com.google.protobuf.Descriptors.FileDescriptor\n"
+    "    descriptor;\n"
+    "static {\n");
+  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 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_)) {
+        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_)) {
+      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/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h
new file mode 100644
index 0000000..080b342
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_file.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_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);
+  ~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/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc
new file mode 100644
index 0000000..6c6f728
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_generator.cc
@@ -0,0 +1,165 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+  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 {
+      *error = "Unknown generator option: " + options[i].first;
+      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));
+  }
+  if (generate_mutable_code) {
+    file_generators.push_back(new FileGenerator(file, /* mutable = */ false));
+  }
+  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/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h
new file mode 100644
index 0000000..47f76be
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc
new file mode 100644
index 0000000..92ef851
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_generator_factory.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.
+
+// 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_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 (descriptor->file()->options().optimize_for() ==
+      FileOptions::LITE_RUNTIME) {
+    return new ImmutableMessageLiteGenerator(descriptor, context_);
+  } else {
+    return new ImmutableMessageGenerator(descriptor, context_);
+  }
+}
+
+ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator(
+    const FieldDescriptor* descriptor) const {
+  return new ImmutableExtensionGenerator(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/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h
new file mode 100644
index 0000000..55365a9
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc
new file mode 100644
index 0000000..e24894b
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h
new file mode 100644
index 0000000..5392d6d
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_helpers.h
@@ -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.
+
+// 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 class have generated parsing, serialization, and other
+// standard methods for which reflection-based fallback implementations exist?
+inline bool HasGeneratedMethods(const Descriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::CODE_SIZE;
+}
+
+// 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) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const EnumDescriptor* descriptor) {
+  return descriptor->file()->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+inline bool HasDescriptorMethods(const FileDescriptor* descriptor) {
+  return descriptor->options().optimize_for() !=
+           FileOptions::LITE_RUNTIME;
+}
+
+// Should we generate generic services for this file?
+inline bool HasGenericServices(const FileDescriptor *file) {
+  return file->service_count() > 0 &&
+         file->options().optimize_for() != FileOptions::LITE_RUNTIME &&
+         file->options().java_generic_services();
+}
+
+inline bool IsLazy(const FieldDescriptor* descriptor) {
+  // Currently, the proto-lite version suports lazy field.
+  // TODO(niwasaki): Support lazy fields also for other proto runtimes.
+  if (descriptor->file()->options().optimize_for() !=
+      FileOptions::LITE_RUNTIME) {
+    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/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc
new file mode 100644
index 0000000..0de8cbe
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h
new file mode 100644
index 0000000..b1b7f28
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
new file mode 100644
index 0000000..283ba1d
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc
@@ -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.
+
+// 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::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  $name$_.merge(other.$name$_);\n"
+    "  $set_has_field_bit_message$;\n"
+    "}\n");
+}
+
+void ImmutableLazyMessageFieldLiteGenerator::
+GenerateParsingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "$name$_.setByteString(input.readBytes(), 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::
+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 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$_).setByteString(\n"
+    "    input.readBytes(), 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$_ = newProtobufList($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$_ = newProtobufList();\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/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h
new file mode 100644
index 0000000..e85ec0f
--- /dev/null
+++ b/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 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(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 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(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/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc
new file mode 100644
index 0000000..3e035c8
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field.cc
@@ -0,0 +1,503 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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,
+                         ClassNameResolver* name_resolver,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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";
+  if (HasDescriptorMethods(descriptor->file())) {
+    (*variables)["lite"] = "";
+    (*variables)["map_field_parameter"] = (*variables)["default_entry"];
+    (*variables)["descriptor"] =
+        name_resolver->GetImmutableClassName(descriptor->file()) +
+        ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) +
+        "_descriptor, ";
+  } else {
+    (*variables)["lite"] = "Lite";
+    (*variables)["map_field_parameter"] = "";
+    (*variables)["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),
+                      name_resolver_, &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$.valueOf($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/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h
new file mode 100644
index 0000000..f2768f3
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc
new file mode 100644
index 0000000..d203940
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc
@@ -0,0 +1,483 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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,
+                         ClassNameResolver* name_resolver,
+                         map<string, string>* variables) {
+  SetCommonFieldVariables(descriptor, info, variables);
+
+  (*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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : "";
+
+  (*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),
+                      name_resolver_, &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::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "internalGetMutable$capitalized_name$().mergeFrom(\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$.valueOf($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/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h
new file mode 100644
index 0000000..a09cd53
--- /dev/null
+++ b/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 GenerateMergingCode(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/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
new file mode 100644
index 0000000..22a70c3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -0,0 +1,1375 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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() {}
+
+// ===================================================================
+// TODO(api): Move this class to a separate immutable_message.cc file.
+ImmutableMessageGenerator::ImmutableMessageGenerator(
+    const Descriptor* descriptor, Context* context)
+  : MessageGenerator(descriptor), context_(context),
+    name_resolver_(context->GetNameResolver()),
+    field_generators_(descriptor, context_) {
+  GOOGLE_CHECK_NE(
+      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+ImmutableMessageGenerator::~ImmutableMessageGenerator() {}
+
+void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
+  // 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 ";
+  }
+
+  // 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 com.google.protobuf.Descriptors.Descriptor\n"
+    "  internal_$identifier$_descriptor;\n");
+
+  // And the FieldAccessorTable.
+  GenerateFieldAccessorTable(printer);
+
+  // 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);
+  }
+}
+
+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) {
+  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 ";
+  }
+  printer->Print(vars,
+    "$private$static\n"
+    "  com.google.protobuf.GeneratedMessage.FieldAccessorTable\n"
+    "    internal_$identifier$_fieldAccessorTable;\n");
+}
+
+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 (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 int value = 0;\n"
+      "private $oneof_capitalized_name$Case(int value) {\n"
+      "  this.value = value;\n"
+      "}\n");
+    printer->Print(vars,
+      "public static $oneof_capitalized_name$Case valueOf(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: throw new java.lang.IllegalArgumentException(\n"
+      "      \"Value is undefined for this oneof enum.\");\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.valueOf(\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 (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.parseWithIOException(PARSER, input);"
+    "}\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.parseWithIOException(PARSER, input, extensionRegistry);"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input);"
+    "}\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.parseDelimitedWithIOException(PARSER, input, extensionRegistry);"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input);"
+    "}\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.parseWithIOException(PARSER, input, extensionRegistry);"
+    "}\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");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    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");
+    }
+  }
+  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",
+      "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"
+      "  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 new RuntimeException(e.setUnfinishedMessage(this));\n"
+      "} catch (java.io.IOException e) {\n"
+      "  throw new RuntimeException(new com.google.protobuf.InvalidProtocolBufferException(e)\n"
+      "      .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 (HasGeneratedMethods(descriptor_)) {
+    // The parsing constructor throws an InvalidProtocolBufferException via a
+    // RuntimeException to aid in method pruning. We unwrap it here.
+    printer->Print(
+        "  try {\n"
+        "    return new $classname$(input, extensionRegistry);\n"
+        "  } catch (RuntimeException e) {\n"
+        "    if (e.getCause() instanceof\n"
+        "        com.google.protobuf.InvalidProtocolBufferException) {\n"
+        "      throw (com.google.protobuf.InvalidProtocolBufferException)\n"
+        "          e.getCause();\n"
+        "    }\n"
+        "    throw e;\n"
+        "  }\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"
+    "    com.google.protobuf.Descriptors.Descriptor descriptor) {\n"
+    "  return \"type.googleapis.com/\" + descriptor.getFullName();\n"
+    "}\n"
+    "\n"
+    "public static <T extends com.google.protobuf.Message> Any pack(\n"
+    "    T message) {\n"
+    "  return Any.newBuilder()\n"
+    "      .setTypeUrl(getTypeUrl(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 getTypeUrl().equals(\n"
+    "      getTypeUrl(defaultInstance.getDescriptorForType()));\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/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
new file mode 100644
index 0000000..be5bfb0
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -0,0 +1,139 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 {
+
+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) = 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);
+
+  // 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);
+
+  // 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/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc
new file mode 100644
index 0000000..5d53503
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder.cc
@@ -0,0 +1,661 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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_NE(
+      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+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 (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.valueOf(\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 (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/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h
new file mode 100644
index 0000000..015ea06
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc
new file mode 100644
index 0000000..8719d00
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_builder_lite.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.
+
+// 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_EQ(
+      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+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);
+  }
+
+  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 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/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h
new file mode 100644
index 0000000..8597b2e
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc
new file mode 100644
index 0000000..b5f8e62
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field.cc
@@ -0,0 +1,1292 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h
new file mode 100644
index 0000000..ea8225a
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc
new file mode 100644
index 0000000..356520e
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc
@@ -0,0 +1,946 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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);
+
+    // 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::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "if (other.has$capitalized_name$()) {\n"
+    "  merge$capitalized_name$(other.get$capitalized_name$());\n"
+    "}\n");
+}
+
+void ImmutableMessageFieldLiteGenerator::
+GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const {
+  // noop for scalars
+}
+
+void ImmutableMessageFieldLiteGenerator::
+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 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::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "merge$capitalized_name$(other.get$capitalized_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$_ = newProtobufList($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::
+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.
+  printer->Print(variables_,
+    "if (!other.$name$_.isEmpty()) {\n"
+    "  if ($name$_.isEmpty()) {\n"
+    "    $name$_ = other.$name$_;\n"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\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$_ = newProtobufList();\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/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h
new file mode 100644
index 0000000..ae26c06
--- /dev/null
+++ b/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 GenerateMergingCode(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 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(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 GenerateMergingCode(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/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc
new file mode 100644
index 0000000..94ed2c3
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.cc
@@ -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.
+
+// 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.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_EQ(
+      FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for());
+}
+
+ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {}
+
+void ImmutableMessageLiteGenerator::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?
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+      .GenerateStaticVariables(printer);
+  }
+}
+
+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();
+
+  GenerateParsingConstructor(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 int value = 0;\n"
+      "private $oneof_capitalized_name$Case(int value) {\n"
+      "  this.value = value;\n"
+      "}\n");
+    printer->Print(vars,
+      "public static $oneof_capitalized_name$Case valueOf(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: throw new java.lang.IllegalArgumentException(\n"
+      "      \"Value is undefined for this oneof enum.\");\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.valueOf(\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);
+
+  if (HasEqualsAndHashCode(descriptor_)) {
+    GenerateEqualsAndHashCode(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 PARSE_PARTIAL_FROM: {\n"
+    "      return new $classname$("
+    "          (com.google.protobuf.CodedInputStream) arg0,\n"
+    "          (com.google.protobuf.ExtensionRegistryLite) arg1);\n"
+    "    }\n"
+    "    case NEW_INSTANCE: {\n"
+    "      return new $classname$(\n"
+    "          com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n"
+    "          com.google.protobuf.ExtensionRegistryLite\n"
+    "              .getEmptyRegistry());\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 MERGE_FROM: {\n");
+
+  printer->Indent();
+  GenerateDynamicMethodMergeFrom(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"
+    "      com.google.protobuf.Internal\n"
+    "          .EMPTY_CODED_INPUT_STREAM,\n"
+    "      com.google.protobuf.ExtensionRegistryLite\n"
+    "          .getEmptyRegistry());\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++) {
+    ImmutableExtensionGenerator(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");
+
+  printer->Print(
+    "private static final long serialVersionUID = 0L;\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 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 parser().parseFrom(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 parser().parseFrom(input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return parser().parseDelimitedFrom(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 parser().parseDelimitedFrom(input, extensionRegistry);\n"
+    "}\n"
+    "public static $classname$ parseFrom(\n"
+    "    com.google.protobuf.CodedInputStream input)\n"
+    "    throws java.io.IOException {\n"
+    "  return parser().parseFrom(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 parser().parseFrom(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::GenerateDynamicMethodMergeFrom(
+    io::Printer* printer) {
+  printer->Print(
+    // Optimization:  If other is the default instance, we know none of its
+    //   fields are set so we can skip the merge.
+    "if (arg0 == $classname$.getDefaultInstance()) return this;\n"
+    "$classname$ other = ($classname$) arg0;\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)).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");
+  }
+
+  // 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(
+    "return this;\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 ImmutableMessageLiteGenerator::
+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);
+    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");
+    }
+  }
+  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");
+  }
+  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");
+
+  // Include the hash of the class so that two objects with different types
+  // but the same field values will probably have different hashes.
+  printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n",
+    "classname", name_resolver_->GetImmutableClassName(descriptor_));
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    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");
+    }
+  }
+
+  printer->Print(
+    "hash = (29 * hash) + unknownFields.hashCode();\n");
+  printer->Print(
+    "memoizedHashCode = hash;\n"
+    "return hash;\n");
+  printer->Outdent();
+  printer->Print(
+    "}\n"
+    "\n");
+}
+
+// ===================================================================
+
+void ImmutableMessageLiteGenerator::
+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++) {
+    ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_)
+      .GenerateExtensionRegistrationCode(printer);
+  }
+}
+
+// ===================================================================
+void ImmutableMessageLiteGenerator::
+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",
+      "classname", descriptor_->name());
+  printer->Indent();
+
+  // Initialize all fields to default.
+  GenerateInitializers(printer);
+
+  // Use builder bits to track mutable repeated fields.
+  int totalBuilderBits = 0;
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const ImmutableFieldLiteGenerator& 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));
+  }
+
+  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_)) {
+    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");
+  }
+
+  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();
+
+  // 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);
+  }
+
+  printer->Print(
+      "doneParsing();\n");
+
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print(
+      "  }\n"     // finally
+      "}\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/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h
new file mode 100644
index 0000000..2bd3cdd
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_message_lite.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.
+
+// 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);
+  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 GenerateDynamicMethodMergeFrom(io::Printer* printer);
+  void GenerateDynamicMethodNewBuilder(io::Printer* printer);
+  void GenerateInitializers(io::Printer* printer);
+  void GenerateEqualsAndHashCode(io::Printer* printer);
+  void GenerateParser(io::Printer* printer);
+  void GenerateParsingConstructor(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/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc
new file mode 100644
index 0000000..0c363f9
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_name_resolver.cc
@@ -0,0 +1,266 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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);
+}
+
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h
new file mode 100644
index 0000000..ab60b0a
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_name_resolver.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.
+
+#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);
+ 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/google/protobuf/compiler/java/java_names.h b/src/google/protobuf/compiler/java/java_names.h
new file mode 100644
index 0000000..0d61433
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc
new file mode 100644
index 0000000..fe52762
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_plugin_unittest.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.
+
+// 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/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.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/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc
new file mode 100644
index 0000000..178bbe1
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field.cc
@@ -0,0 +1,866 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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);
+  if (descriptor->is_packed()) {
+    (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag(
+        descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED));
+  } else {
+    (*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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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() &&
+      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/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h
new file mode 100644
index 0000000..d0cd12d
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
new file mode 100644
index 0000000..5a7bf82
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc
@@ -0,0 +1,911 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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)["new_list"] = "new" + capitalized_type + "List";
+      (*variables)["new_list_with_capacity"] =
+          "new" + capitalized_type + "ListWithCapacity";
+      (*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;
+      break;
+    default:
+      (*variables)["field_list_type"] =
+          "com.google.protobuf.Internal.ProtobufList<" +
+          (*variables)["boxed_type"] + ">";
+      (*variables)["new_list"] = "newProtobufList";
+      (*variables)["new_list_with_capacity"] = "newProtobufListWithCapacity";
+      (*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";
+  }
+
+  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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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);
+
+    // 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::
+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 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::
+GenerateMergingCode(io::Printer* printer) const {
+  printer->Print(variables_,
+    "set$capitalized_name$(other.get$capitalized_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() &&
+      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$_ = $new_list$($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::
+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"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\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$_ = $new_list$();\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$_ = $new_list$();\n");
+  } else {
+    printer->Print(variables_,
+      "  $name$_ = $new_list_with_capacity$(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/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h
new file mode 100644
index 0000000..ad603c2
--- /dev/null
+++ b/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 GenerateMergingCode(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 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(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 GenerateMergingCode(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/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc
new file mode 100644
index 0000000..11bfc12
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h
new file mode 100644
index 0000000..6707e82
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
new file mode 100644
index 0000000..7017736
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc
@@ -0,0 +1,205 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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), 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_)) {
+    // 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/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h
new file mode 100644
index 0000000..38a32fc
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_shared_code_generator.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.
+
+// 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 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_;
+  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/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc
new file mode 100644
index 0000000..7f757e4
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_field.cc
@@ -0,0 +1,1023 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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 if (!HasDescriptorMethods(descriptor_->file())) {
+    // 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_,
+      "java.lang.String s = input.readString();\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 if (!HasDescriptorMethods(descriptor_->file())) {
+    // 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_,
+      "java.lang.String s = input.readString();\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 if (!HasDescriptorMethods(descriptor_->file())) {
+    // 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_,
+    "java.lang.String s = input.readString();\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_) || !HasDescriptorMethods(descriptor_->file())) {
+    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/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h
new file mode 100644
index 0000000..a3b5735
--- /dev/null
+++ b/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/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc
new file mode 100644
index 0000000..eb5964b
--- /dev/null
+++ b/src/google/protobuf/compiler/java/java_string_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)
+// 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 " : "";
+  (*variables)["on_changed"] =
+      HasDescriptorMethods(descriptor->containing_type()) ? "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);
+
+    // 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"] =
+        "!get" + (*variables)["capitalized_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::
+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_message$\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 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::
+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 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$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList(\n"
+    "        $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::
+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"
+    "  } else {\n"
+    "    ensure$capitalized_name$IsMutable();\n"
+    "    $name$_.addAll(other.$name$_);\n"
+    "  }\n"
+    "  $on_changed$\n"
+    "}\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$_ = com.google.protobuf.GeneratedMessageLite.newProtobufList();\n"
+    "}\n");
+  if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) {
+    printer->Print(variables_,
+      "$name$_.add(s);\n");
+  } else {
+    printer->Print(variables_,
+      "$name$_.add(bs);\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/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h
new file mode 100644
index 0000000..4d9b4bd
--- /dev/null
+++ b/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 GenerateMergingCode(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 GenerateMergingCode(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 GenerateMergingCode(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/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
new file mode 100644
index 0000000..c6e8dfe
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_enum.h b/src/google/protobuf/compiler/javanano/javanano_enum.h
new file mode 100644
index 0000000..10dd364
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
new file mode 100644
index 0000000..7666db3
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
new file mode 100644
index 0000000..b94790d
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
new file mode 100644
index 0000000..0b9d1d8
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_extension.h b/src/google/protobuf/compiler/javanano/javanano_extension.h
new file mode 100644
index 0000000..4843e29
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc
new file mode 100644
index 0000000..85257f3
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
new file mode 100644
index 0000000..57c221f
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_file.cc b/src/google/protobuf/compiler/javanano/javanano_file.cc
new file mode 100644
index 0000000..3676ab9
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_file.h b/src/google/protobuf/compiler/javanano/javanano_file.h
new file mode 100644
index 0000000..217eafe
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
new file mode 100644
index 0000000..a33eba1
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -0,0 +1,232 @@
+// 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 (!file->options().javanano_use_deprecated_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/google/protobuf/compiler/javanano/javanano_generator.h b/src/google/protobuf/compiler/javanano/javanano_generator.h
new file mode 100644
index 0000000..6f9f7f2
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
new file mode 100644
index 0000000..5465655
--- /dev/null
+++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc
@@ -0,0 +1,593 @@
+// 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 (!file->options().javanano_use_deprecated_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/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h
new file mode 100644
index 0000000..014c85a
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc
new file mode 100644
index 0000000..83b2b0c
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h
new file mode 100644
index 0000000..c01bde3
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
new file mode 100644
index 0000000..a41da5a
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
new file mode 100644
index 0000000..281ec64
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
new file mode 100644
index 0000000..d1d04b5
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
new file mode 100644
index 0000000..e074735
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
new file mode 100644
index 0000000..e3b4bb9
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
new file mode 100644
index 0000000..978abf2
--- /dev/null
+++ b/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/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
new file mode 100644
index 0000000..a01981d
--- /dev/null
+++ b/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/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc
new file mode 100755
index 0000000..e6c3b36
--- /dev/null
+++ b/src/google/protobuf/compiler/js/js_generator.cc
@@ -0,0 +1,2622 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 {
+
+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.
+string StripProto(const string& filename) {
+  const char* suffix = HasSuffixString(filename, ".protodevel")
+      ? ".protodevel" : ".proto";
+  return StripSuffixString(filename, suffix);
+}
+
+// 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();
+}
+
+// - 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;
+}
+
+// Returns the message/response ID, if set.
+string GetMessageId(const Descriptor* desc) {
+  return string();
+}
+
+
+// Used inside Google only -- do not remove.
+bool IsResponse(const Descriptor* desc) { return false; }
+bool IgnoreField(const FieldDescriptor* field) { return false; }
+
+
+// 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;
+}
+
+// Returns the field name as a capitalized portion of a getter/setter method
+// name, e.g. MyField for .getMyField().
+string JSGetterName(const FieldDescriptor* field) {
+  string name = JSIdent(field,
+                        /* is_upper_camel = */ true,
+                        /* is_map = */ false);
+  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. Since JS strings are UTF-16, we only
+// need to handle the BMP (16-bit range) here.
+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. |is_utf8| determines whether the input data (in a C++ string of
+// chars) is UTF-8 encoded (in which case codepoints become JavaScript string
+// characters, escaped with 16-bit hex escapes where necessary) or raw binary
+// (in which case bytes become JavaScript string characters 0 -- 255).
+string EscapeJSString(const string& in, bool is_utf8) {
+  string result;
+  size_t decoded = 0;
+  for (size_t i = 0; i < in.size(); i += decoded) {
+    uint16 codepoint = 0;
+    if (is_utf8) {
+      // 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) {
+        break;
+      }
+      decoded = have_bytes;
+    } else {
+      codepoint = static_cast<uint16>(static_cast<uint8>(in[i]));
+      decoded = 1;
+    }
+
+    // Next byte -- used for minimal octal escapes below.
+    char next_byte = (i + decoded) < in.size() ?
+        in[i + decoded] : 0;
+    bool pad_octal = (next_byte >= '0' && next_byte <= '7');
+
+    switch (codepoint) {
+      case '\0': result += pad_octal ? "\\000" : "\\0";   break;
+      case '\b': result += "\\\b";  break;
+      case '\t': result += "\\\t";  break;
+      case '\n': result += "\\\n";  break;
+      case '\r': result += "\\\r";  break;
+      case '\f': result += "\\\f";  break;
+      case '\\': result += "\\\\";  break;
+      case '"':  result += pad_octal ? "\\042" : "\\42"; break;
+      case '&':  result += pad_octal ? "\\046" : "\\46"; break;
+      case '\'': result += pad_octal ? "\\047" : "\\47"; break;
+      case '<':  result += pad_octal ? "\\074" : "\\74"; break;
+      case '=':  result += pad_octal ? "\\075" : "\\75"; break;
+      case '>':  result += pad_octal ? "\\076" : "\\76"; break;
+      default:
+        // All other non-ASCII codepoints are escaped.
+        // Original codegen uses hex for >= 0x100 and octal for others.
+        if (codepoint >= 0x20 && codepoint <= 0x7e) {
+          result += static_cast<char>(codepoint);
+        } else {
+          if (codepoint >= 0x100) {
+            result += StringPrintf("\\u%04x", codepoint);
+          } else {
+            if (pad_octal || codepoint >= 0100) {
+              result += "\\";
+              result += ('0' + ((codepoint >> 6) & 07));
+              result += ('0' + ((codepoint >> 3) & 07));
+              result += ('0' + ((codepoint >> 0) & 07));
+            } else if (codepoint >= 010) {
+              result += "\\";
+              result += ('0' + ((codepoint >> 3) & 07));
+              result += ('0' + ((codepoint >> 0) & 07));
+            } else {
+              result += "\\";
+              result += ('0' + ((codepoint >> 0) & 07));
+            }
+          }
+        }
+        break;
+    }
+  }
+  return result;
+}
+
+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) {
+        return "\"" + EscapeJSString(field->default_value_string(), true) +
+               "\"";
+      } else {
+        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 JSTypeName(const GeneratorOptions& options,
+                  const FieldDescriptor* field) {
+  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 "string";
+    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,
+                             bool always_singular) {
+  bool is_primitive =
+      (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
+       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE);
+
+  string jstype = JSTypeName(options, field);
+
+  if (field->is_repeated() &&
+      !always_singular &&
+      (field->is_packed() || !singular_if_not_packed)) {
+    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 (is_writer && field->type() == FieldDescriptor::TYPE_BYTES) {
+    // Override for `bytes` fields: treat string as raw bytes, not base64.
+    name = "BytesRawString";
+  }
+  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 Descriptor* desc) {
+  if (desc->full_name() == "google.protobuf.bridge.MessageSet") {
+    return "jspb.Message.messageSetExtensions";
+  } else {
+    return GetPath(options, 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) {
+  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";
+  }
+  return comments;
+}
+
+bool ShouldGenerateExtension(const FieldDescriptor* field) {
+  return
+      field->is_extension() &&
+      !IgnoreField(field);
+}
+
+bool HasExtensions(const Descriptor* desc) {
+  if (desc->extension_count() > 0) {
+    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 https://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 https://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:
+      return "\"\"";
+
+    default:
+      // BYTES and MESSAGE are handled separately.
+      assert(false);
+      return "";
+  }
+}
+
+}  // 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::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++) {
+    for (int j = 0; j < files[i]->message_type_count(); j++) {
+      FindProvidesForMessage(options, printer, files[i]->message_type(j),
+                                 provided);
+    }
+    for (int j = 0; j < files[i]->enum_type_count(); j++) {
+      FindProvidesForEnum(options, printer, files[i]->enum_type(j),
+                              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::GenerateRequires(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::GenerateRequires(const GeneratorOptions& options,
+                                 io::Printer* printer,
+                                 const vector<const FileDescriptor*>& files,
+                                 std::set<string>* provided) const {
+  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::GenerateRequires(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);
+    }
+  }
+
+  // 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),
+        "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", GetPath(options, field->message_type()));
+      }
+    } else {
+      printer->Print("(f = msg.get$getter$()) && "
+                     "$type$.toObject(includeInstance, f)",
+                     "getter", JSGetterName(field),
+                     "type", GetPath(options, field->message_type()));
+    }
+  } else {
+    // Simple field (singular or repeated).
+    if (!HasFieldPresence(field) && !field->is_repeated()) {
+      // Delegate to the generated get<field>() method in order not to duplicate
+      // the proto3-field-default-value logic here.
+      printer->Print("msg.get$getter$()",
+                     "getter", JSGetterName(field));
+    } else {
+      if (field->has_default_value()) {
+        printer->Print("jspb.Message.getField(msg, $index$) != null ? "
+                       "jspb.Message.getField(msg, $index$) : $defaultValue$",
+                       "index", JSFieldIndex(field),
+                       "defaultValue", JSFieldDefault(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", GetPath(options, field->message_type()));
+      }
+    } 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", GetPath(options, field->message_type()));
+    }
+  } 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 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),
+        "type", JSFieldTypeAnnotation(options, field,
+                                      /* force_optional = */ false,
+                                      /* force_present = */ false,
+                                      /* singular_if_not_packed = */ false,
+                                      /* always_singular = */ 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,
+                                      /* always_singular = */ false),
+        "rpt", (field->is_repeated() ? "Repeated" : ""),
+        "index", JSFieldIndex(field),
+        "wrapperclass", GetPath(options, field->message_type()),
+        "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,
+                              /* always_singular = */ 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 {
+    string typed_annotation;
+
+    // Simple (primitive) field, either singular or repeated.
+    {
+      typed_annotation = JSFieldTypeAnnotation(options, field,
+                              /* force_optional = */ false,
+                              /* force_present = */ !HasFieldPresence(field),
+                              /* singular_if_not_packed = */ false,
+                              /* always_singular = */ false),
+      printer->Print(
+          "/**\n"
+          " * $fielddef$\n"
+          "$comment$"
+          " * @return {$type$}\n"
+          " */\n",
+          "fielddef", FieldDefinition(options, field),
+          "comment", FieldComments(field),
+          "type", typed_annotation);
+    }
+
+    printer->Print(
+        "$class$.prototype.get$name$ = function() {\n",
+        "class", GetPath(options, field->containing_type()),
+        "name", JSGetterName(field));
+
+    {
+      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 ? "
+                       "jspb.Message.getField(this, $index$) : $defaultValue$",
+                       "index", JSFieldIndex(field),
+                       "defaultValue", JSFieldDefault(field));
+      } else {
+        printer->Print("jspb.Message.getField(this, $index$)",
+                       "index", JSFieldIndex(field));
+      }
+    }
+
+    {
+      printer->Print(
+          ");\n"
+          "};\n"
+          "\n"
+          "\n");
+    }
+
+    {
+      printer->Print(
+          "/** @param {$optionaltype$} value $returndoc$ */\n",
+          "optionaltype",
+          JSFieldTypeAnnotation(options, field,
+                                /* force_optional = */ true,
+                                /* force_present = */ !HasFieldPresence(field),
+                                /* singular_if_not_packed = */ false,
+                                /* always_singular = */ 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", "",
+        "typeclose", "",
+        "oneofgroup",
+        (field->containing_oneof() ? (", " + JSOneofArray(options, field))
+                                   : ""),
+        "returnvalue", JSReturnClause(field), "rptvalueinit",
+        (field->is_repeated() ? " || []" : ""));
+
+
+    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),
+        "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", GetPath(options, field->message_type()),
+        "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,
+                                           /* always_singular = */ false),
+        "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$().
+    printer->Print(
+        "      msg.get$name$().push(value);\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),
+        "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));
+
+  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),
+      "name", JSGetterName(field),
+      "index", SimpleItoa(field->number()));
+
+  if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+    printer->Print(
+        ",\n"
+        "      $submsg$.serializeBinaryToWriter\n",
+        "submsg", GetPath(options, field->message_type()));
+  } 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,
+          /* always_singular = */ 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 ?
+               GetPath(options, field->message_type()) : string("null")),
+      "toObject", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ?
+                   (GetPath(options, field->message_type()) + ".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) ?
+        (GetPath(options, field->message_type()) +
+         ".serializeBinaryToWriter") : "null",
+        "binaryMessageDeserializeFn",
+        (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ?
+        (GetPath(options, field->message_type()) +
+         ".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->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 {
+      // 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;
+    }
+  }
+
+  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);
+  }
+}
+
+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;
+  }
+
+
+  // We're either generating a single library file with definitions for message
+  // and enum types in *all* FileDescriptor inputs, or we're generating a single
+  // file for each type.
+  if (options.library != "") {
+    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);
+    GenerateRequires(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 {
+    // Collect all types, and print each type to a separate file. Pull out
+    // free-floating extensions while we make this pass.
+    map< string, vector<const FieldDescriptor*> > extensions_by_namespace;
+
+    // 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.
+
+    // Current descriptor that will generate each filename, indexed by filename.
+    map<string, const void*> desc_by_filename;
+    // Set of descriptors allowed to generate files.
+    set<const void*> allowed_descs;
+
+    for (int i = 0; i < files.size(); i++) {
+      // Collect all (descriptor, filename) pairs.
+      map<const void*, string> descs_in_file;
+      for (int j = 0; j < files[i]->message_type_count(); j++) {
+        const Descriptor* desc = files[i]->message_type(j);
+        string filename =
+            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+        descs_in_file[desc] = filename;
+      }
+      for (int j = 0; j < files[i]->enum_type_count(); j++) {
+        const EnumDescriptor* desc = files[i]->enum_type(j);
+        string filename =
+            options.output_dir + "/" + ToFileName(desc->name()) + ".js";
+        descs_in_file[desc] = filename;
+      }
+
+      // For each (descriptor, filename) pair, update the
+      // descriptors-by-filename map, and if a previous descriptor was already
+      // writing the filename, remove it from the allowed-descriptors set.
+      map<const void*, string>::iterator it;
+      for (it = descs_in_file.begin(); it != descs_in_file.end(); ++it) {
+        const void* desc = it->first;
+        const string& filename = it->second;
+        if (desc_by_filename.find(filename) != desc_by_filename.end()) {
+          if (options.error_on_name_conflict) {
+            *error = "Name conflict: file name " + filename +
+                     " would be generated by two descriptors";
+            return false;
+          }
+          allowed_descs.erase(desc_by_filename[filename]);
+        }
+        desc_by_filename[filename] = desc;
+        allowed_descs.insert(desc);
+      }
+    }
+
+    // Generate code.
+    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_descs.find(desc) == allowed_descs.end()) {
+          continue;
+        }
+
+        string filename = options.output_dir + "/" +
+            ToFileName(desc->name()) + ".js";
+        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);
+        GenerateRequires(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_descs.find(enumdesc) == allowed_descs.end()) {
+          continue;
+        }
+
+        string filename = options.output_dir + "/" +
+            ToFileName(enumdesc->name()) + ".js";
+
+        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;
+        }
+      }
+      // Pull out all free-floating extensions and generate files for those too.
+      for (int j = 0; j < file->extension_count(); j++) {
+        const FieldDescriptor* extension = file->extension(j);
+        extensions_by_namespace[GetPath(options, files[i])]
+            .push_back(extension);
+      }
+    }
+
+    // Generate extensions in separate files.
+    map< string, vector<const FieldDescriptor*> >::iterator it;
+    for (it = extensions_by_namespace.begin();
+         it != extensions_by_namespace.end();
+         ++it) {
+      string filename = options.output_dir + "/" +
+          ToFileName(it->first) + ".js";
+
+      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;
+      FindProvidesForFields(options, &printer, it->second, &provided);
+      GenerateProvides(options, &printer, &provided);
+      GenerateTestOnly(options, &printer);
+      GenerateRequires(options, &printer, it->second, &provided);
+
+      for (int j = 0; j < it->second.size(); j++) {
+        if (ShouldGenerateExtension(it->second[j])) {
+          GenerateExtension(options, &printer, it->second[j]);
+        }
+      }
+    }
+  }
+
+  return true;
+}
+
+}  // namespace js
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/js/js_generator.h b/src/google/protobuf/compiler/js/js_generator.h
new file mode 100755
index 0000000..db2dceb
--- /dev/null
+++ b/src/google/protobuf/compiler/js/js_generator.h
@@ -0,0 +1,265 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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;
+
+  GeneratorOptions()
+      : add_require_for_enums(false),
+        testonly(false),
+        output_dir("."),
+        namespace_prefix(""),
+        library(""),
+        error_on_name_conflict(false),
+        binary(false) {}
+
+  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 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 GenerateRequires(const GeneratorOptions& options,
+                        io::Printer* printer,
+                        const vector<const FileDescriptor*>& file,
+                        std::set<string>* provided) const;
+  void GenerateRequires(const GeneratorOptions& options,
+                        io::Printer* printer,
+                        const Descriptor* desc,
+                        std::set<string>* provided) const;
+  // For extension fields at file scope.
+  void GenerateRequires(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;
+
+  // 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/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
new file mode 100644
index 0000000..97df536
--- /dev/null
+++ b/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_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/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
new file mode 100644
index 0000000..121d917
--- /dev/null
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -0,0 +1,249 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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 <memory>
+#ifndef _SHARED_PTR_H
+#include <google/protobuf/stubs/shared_ptr.h>
+#endif
+
+#include <google/protobuf/testing/file.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/stubs/stl_util.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/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
new file mode 100644
index 0000000..8c8348d
--- /dev/null
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -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.
+
+// 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 {
+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/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
new file mode 100644
index 0000000..d6f01c6
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -0,0 +1,198 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 GPB_ENUM($name$) {\n",
+                 "comments", enum_comments,
+                 "name", name_);
+  printer->Indent();
+
+  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+    // Include the unknown value.
+    printer->Print(
+      "$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$ = $value$,\n",
+        "name", EnumValueName(all_values_[i]),
+        "value", SimpleItoa(all_values_[i]->number()));
+  }
+  printer->Outdent();
+  printer->Print(
+      "};\n"
+      "\n"
+      "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
+      "\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_);
+
+  printer->Print(
+      "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+      "  static GPBEnumDescriptor *descriptor = NULL;\n"
+      "  if (!descriptor) {\n"
+      "    static GPBMessageEnumValueDescription values[] = {\n",
+      "name", name_);
+  printer->Indent();
+  printer->Indent();
+  printer->Indent();
+
+  // 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;
+
+  for (int i = 0; i < all_values_.size(); i++) {
+    ++enum_value_description_key;
+    string short_name(EnumValueShortName(all_values_[i]));
+    printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
+                   "short_name", short_name,
+                   "name", EnumValueName(all_values_[i]));
+    if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
+      text_format_decode_data.AddString(enum_value_description_key, short_name,
+                                        all_values_[i]->name());
+    }
+  }
+  printer->Outdent();
+  printer->Outdent();
+  printer->Outdent();
+  printer->Print("    };\n");
+  if (text_format_decode_data.num_entries() == 0) {
+    printer->Print(
+        "    descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                                   values:values\n"
+        "                                               valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+        "                                             enumVerifier:$name$_IsValidValue];\n",
+        "name", name_);
+    } else {
+      printer->Print(
+        "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+        "    descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+        "                                                   values:values\n"
+        "                                               valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+        "                                             enumVerifier:$name$_IsValidValue\n"
+        "                                      extraTextFormatInfo:extraTextFormatInfo];\n",
+        "name", name_,
+        "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+    }
+    printer->Print(
+      "  }\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/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
new file mode 100644
index 0000000..0b41cf7
--- /dev/null
+++ b/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/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
new file mode 100644
index 0000000..30a13dd
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_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 <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";
+
+  const Descriptor* msg_descriptor = descriptor->containing_type();
+  (*variables)["owning_message_class"] = ClassName(msg_descriptor);
+}
+}  // namespace
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
+    : SingleFieldGenerator(descriptor) {
+  SetEnumVariables(descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionDeclarations(
+    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"
+      "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 {
+  // 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)
+    : RepeatedFieldGenerator(descriptor) {
+  SetEnumVariables(descriptor, &variables_);
+  variables_["array_storage_type"] = "GPBEnumArray";
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "  .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
new file mode 100644
index 0000000..b629eae
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.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_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);
+
+ public:
+  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+  virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+  virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+ protected:
+  explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~EnumFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+  RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+  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/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
new file mode 100644
index 0000000..4e34839
--- /dev/null
+++ b/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"
+                 "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+                 "  .dataType = $extension_type$,\n"
+                 "  .extendedClass = GPBStringifySymbol($extended_type$),\n"
+                 "  .fieldNumber = $number$,\n"
+                 "  .defaultValue.$default_name$ = $default$,\n"
+                 "  .messageOrGroupClassName = $type$,\n"
+                 "  .options = $options$,\n"
+                 "  .enumDescriptorFunc = $enum_desc_func_name$,\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/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
new file mode 100644
index 0000000..e361e63
--- /dev/null
+++ b/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/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
new file mode 100644
index 0000000..cf5d8cf
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -0,0 +1,434 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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_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)["has_index"] = SimpleItoa(descriptor->index());
+  (*variables)["field_type"] = GetCapitalizedType(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";
+
+  string field_options = descriptor->options().SerializeAsString();
+  // Must convert to a standard byte order for packing length into
+  // a cstring.
+  uint32 length = ghtonl(field_options.length());
+  if (length > 0) {
+    string bytes((const char*)&length, sizeof(length));
+    bytes.append(field_options);
+    string options_str = "\"" + CEscape(bytes) + "\"";
+    (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
+  } else {
+    (*variables)["fieldoptions"] = "";
+  }
+
+  // Clear some common things so they can be set just when needed.
+  (*variables)["storage_attribute"] = "";
+}
+
+}  // namespace
+
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+  FieldGenerator* result = NULL;
+  if (field->is_repeated()) {
+    switch (GetObjectiveCType(field)) {
+      case OBJECTIVECTYPE_MESSAGE: {
+        if (field->is_map()) {
+          result = new MapFieldGenerator(field);
+        } else {
+          result = new RepeatedMessageFieldGenerator(field);
+        }
+        break;
+      }
+      case OBJECTIVECTYPE_ENUM:
+        result = new RepeatedEnumFieldGenerator(field);
+        break;
+      default:
+        result = new RepeatedPrimitiveFieldGenerator(field);
+        break;
+    }
+  } else {
+    switch (GetObjectiveCType(field)) {
+      case OBJECTIVECTYPE_MESSAGE: {
+        result = new MessageFieldGenerator(field);
+        break;
+      }
+      case OBJECTIVECTYPE_ENUM:
+        result = new EnumFieldGenerator(field);
+        break;
+      default:
+        if (IsReferenceType(field)) {
+          result = new PrimitiveObjFieldGenerator(field);
+        } else {
+          result = new PrimitiveFieldGenerator(field);
+        }
+        break;
+    }
+  }
+  result->FinishInitialization();
+  return result;
+}
+
+
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+    : 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) const {
+  printer->Print(
+      variables_,
+      "{\n"
+      "  .name = \"$name$\",\n"
+      "  .number = $field_number_name$,\n"
+      "  .hasIndex = $has_index$,\n"
+      "  .flags = $fieldflags$,\n"
+      "  .dataType = GPBDataType$field_type$,\n"
+      "  .offset = offsetof($classname$__storage_, $name$),\n"
+      "  .defaultValue.$default_name$ = $default$,\n");
+
+  // TODO(thomasvl): It might be useful to add a CPP wrapper to support
+  // compiling away the EnumDescriptors.  To do that, we'd need a #if here
+  // to control setting the descriptor vs. the validator, and above in
+  // SetCommonFieldVariables() we'd want to wrap how we add
+  // GPBFieldHasDefaultValue to the flags.
+
+  // "  .dataTypeSpecific.value* = [something],"
+  GenerateFieldDescriptionTypeSpecific(printer);
+
+  const string& field_options(variables_.find("fieldoptions")->second);
+  if (field_options.empty()) {
+    printer->Print("  .fieldOptions = NULL,\n");
+  } else {
+    // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
+    // outdented because the need for indent captured on the previous
+    // printing of a \n and there is no way to get the current indent level
+    // to call the right number of Outdent()/Indents() to maintain state.
+    printer->Print(
+        variables_,
+        "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
+        "  .fieldOptions = $fieldoptions$,\n"
+        "#else\n"
+        "  .fieldOptions = NULL,\n"
+        "#endif  // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+  }
+
+  printer->Print("},\n");
+}
+
+void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
+    io::Printer* printer) const {
+  printer->Print(
+      variables_,
+      "  .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n");
+}
+
+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)
+    : FieldGenerator(descriptor) {
+  // 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$");
+  if (WantsHasProperty()) {
+    printer->Print(
+        variables_,
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+  }
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite) $property_type$ $name$;\n"
+      "\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;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(
+    const FieldDescriptor* descriptor)
+    : SingleFieldGenerator(descriptor) {
+  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$");
+  if (WantsHasProperty()) {
+    printer->Print(
+        variables_,
+        "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+  }
+  printer->Print(
+      variables_,
+      "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_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;\n");
+  }
+  printer->Print("\n");
+}
+
+RepeatedFieldGenerator::RepeatedFieldGenerator(
+    const FieldDescriptor* descriptor)
+    : ObjCObjFieldGenerator(descriptor) {
+  // Repeated fields don't use the has index.
+  variables_["has_index"] = "GPBNoHasBit";
+}
+
+RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
+
+void RepeatedFieldGenerator::FinishInitialization(void) {
+  FieldGenerator::FinishInitialization();
+  variables_["array_comment"] =
+      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
+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_storage_type$ *$name$$storage_attribute$;\n"
+      "@property(nonatomic, readonly) NSUInteger $name$_Count;\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_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+  }
+  printer->Print("\n");
+}
+
+bool RepeatedFieldGenerator::WantsHasProperty(void) const {
+  // Consumer check the array size/existance rather than a has bit.
+  return false;
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+    : 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)));
+  }
+  for (int i = 0; i < descriptor->extension_count(); i++) {
+    extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+  }
+}
+
+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];
+}
+
+void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_[i]->SetOneofIndexBase(index_base);
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
new file mode 100644
index 0000000..130a52d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.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_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);
+
+  virtual ~FieldGenerator();
+
+  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
+  virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
+
+  virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
+
+  virtual void GenerateFieldDescription(io::Printer* printer) const;
+  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+  virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+  virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+  virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+  virtual void DetermineForwardDeclarations(set<string>* fwd_decls) const;
+
+  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:
+  explicit FieldGenerator(const FieldDescriptor* descriptor);
+
+  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;
+
+ protected:
+  explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
+  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:
+  explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+
+ 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;
+
+ protected:
+  explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+  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:
+  explicit FieldGeneratorMap(const Descriptor* descriptor);
+  ~FieldGeneratorMap();
+
+  const FieldGenerator& get(const FieldDescriptor* field) const;
+  const FieldGenerator& get_extension(int index) const;
+
+  void SetOneofIndexBase(int index_base);
+
+ 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/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
new file mode 100644
index 0000000..228c66f
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -0,0 +1,368 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 = 30000;
+
+namespace compiler {
+namespace objectivec {
+
+FileGenerator::FileGenerator(const FileDescriptor *file)
+    : file_(file),
+      root_class_name_(FileClassName(file)),
+      is_public_dep_(false) {
+  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));
+    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"
+      "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"
+      "@interface $root_class_name$ : GPBRootObject\n"
+      "\n"
+      "// The base class provides:\n"
+      "//   + (GPBExtensionRegistry *)extensionRegistry;\n"
+      "// which is an GPBExtensionRegistry that includes all the extensions defined by\n"
+      "// this file and all files that it depends on.\n"
+      "\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"
+      "// @@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");
+
+  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"
+    "// @@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));
+      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/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
new file mode 100644
index 0000000..1bb4f0e
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.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.
+
+#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:
+  explicit FileGenerator(const FileDescriptor* file);
+  ~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 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/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
new file mode 100644
index 0000000..375b4e0
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -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.
+
+#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 {
+  // ObjC doesn't have any options at the moment, error if passed one.
+  vector<pair<string, string> > options;
+  ParseGeneratorParameter(parameter, &options);
+  for (int i = 0; i < options.size(); i++) {
+    *error = "error:: Unknown generator option: " + options[i].first;
+    return false;
+  }
+
+  // Validate the objc prefix/package pairing.
+  if (!ValidateObjCClassPrefix(file, error)) {
+    // *error will have been filled in.
+    return false;
+  }
+
+  FileGenerator file_generator(file);
+  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/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
new file mode 100644
index 0000000..09266b0
--- /dev/null
+++ b/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/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
new file mode 100644
index 0000000..8527b74
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -0,0 +1,1238 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 {
+
+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);
+
+  for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+    string value = *i;
+    bool all_upper = (kUpperSegments.count(value) > 0);
+    for (int j = 0; j < value.length(); j++) {
+      if (j == 0 || all_upper) {
+        value[j] = ascii_toupper(value[j]);
+      } else {
+        // Nothing, already in lower.
+      }
+    }
+    *i = value;
+  }
+  string result;
+  for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+    result += *i;
+  }
+  if ((result.length() != 0) && !first_capitalized) {
+    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();
+  }
+}
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+  return StringReplace(to_escape, "?", "\\?", true);
+}
+
+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
+
+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*)\"" + 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;
+}
+
+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++) {
+    // We use $ for delimiters, so replace comments with dollars with
+    // html escaped version.
+    // None of the other compilers handle this (as of this writing) but we
+    // ran into it once, so just to be safe.
+    final_comments +=
+        prefix + StringReplace(lines[i], "$", "&#36;", 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(map<string, string>* prefix_map,
+                                 string* out_expect_file_path,
+                                 string* out_error) {
+  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+  if (file_path == NULL) {
+    return true;
+  }
+
+  int fd;
+  do {
+    fd = open(file_path, O_RDONLY);
+  } while (fd < 0 && errno == EINTR);
+  if (fd < 0) {
+    *out_error =
+        string(file_path) + ":0:0: error: Unable to open." + strerror(errno);
+    return false;
+  }
+  io::FileInputStream file_stream(fd);
+  file_stream.SetCloseOnDelete(true);
+  *out_expect_file_path = file_path;
+
+  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(file_path) + ":" + SimpleItoa(parser.last_line()) +
+                   ":0: error: " + parser.error_str();
+      return false;
+    }
+  }
+  return parser.Finish();
+}
+
+}  // namespace
+
+bool ValidateObjCClassPrefix(const FileDescriptor* file, 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;
+  string expect_file_path;
+  if (!LoadExpectedPackagePrefixes(&expected_package_prefixes,
+                                   &expect_file_path, out_error)) {
+    // Any error, clear the entries that were read.
+    expected_package_prefixes.clear();
+  }
+
+  // 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 = "protoc:0: error: Expected 'option objc_class_prefix = \"" +
+                   package_match->second + "\";' 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 =
+          "protoc:0: 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 (" +
+          expect_file_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 ("
+         << expect_file_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/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
new file mode 100644
index 0000000..8574486
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -0,0 +1,175 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 {
+
+// 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
+};
+
+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);
+
+string BuildFlagsString(const vector<string>& strings);
+
+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, 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/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
new file mode 100644
index 0000000..dc1cef5
--- /dev/null
+++ b/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/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
new file mode 100644
index 0000000..2987f3d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -0,0 +1,163 @@
+// 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)
+    : RepeatedFieldGenerator(descriptor) {
+  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));
+
+  // 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);
+  if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+      ((value_objc_type == OBJECTIVECTYPE_STRING) ||
+       (value_objc_type == OBJECTIVECTYPE_DATA) ||
+       (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+    variables_["array_storage_type"] = "NSMutableDictionary";
+  } else {
+    string base_name = MapEntryTypeName(key_descriptor, true);
+    base_name += MapEntryTypeName(value_descriptor, false);
+    base_name += "Dictionary";
+    variables_["array_storage_type"] = "GPB" + base_name;
+  }
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  // Use the array_comment suport in RepeatedFieldGenerator to output what the
+  // values in the map are.
+  const FieldDescriptor* value_descriptor =
+      descriptor_->message_type()->FindFieldByName("value");
+  ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+  if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
+      (value_objc_type == OBJECTIVECTYPE_DATA) ||
+      (value_objc_type == OBJECTIVECTYPE_STRING) ||
+      (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+    variables_["array_comment"] =
+        "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+  } else {
+    variables_["array_comment"] = "";
+  }
+}
+
+void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+    io::Printer* printer) const {
+  // Relay it to the value generator to provide enum validator, message
+  // class, etc.
+  value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
new file mode 100644
index 0000000..173541f
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -0,0 +1,64 @@
+// 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);
+
+ public:
+  virtual void FinishInitialization(void);
+  virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+  explicit MapFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~MapFieldGenerator();
+
+ 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/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
new file mode 100644
index 0000000..32671d4
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -0,0 +1,647 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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. Bools (1 byte)
+  //   2. Anything always 4 bytes - float, *32, enums
+  //   3. Anything that is always a pointer (they will be 8 bytes on 64 bit
+  //      builds and 4 bytes on 32bit builds.
+  //   4. Anything always 8 bytes - double, *64
+  //
+  // 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;
+
+    // 1 byte.
+    case FieldDescriptor::TYPE_BOOL:
+      return 1;
+  }
+
+  // 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)
+    : root_classname_(root_classname),
+      descriptor_(descriptor),
+      field_generators_(descriptor),
+      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));
+    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);
+      // If it is a the field is repeated, the type will be and *Array, and we
+      // don't need any forward decl.
+      if (fieldDescriptor->is_repeated()) {
+        continue;
+      }
+      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$@interface $classname$ : GPBMessage\n\n",
+      "classname", class_name_,
+      "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());
+
+    // TODO(thomasvl): Finish optimizing has bit. The current behavior is as
+    // follows:
+    // 1. objectivec_field.cc's SetCommonFieldVariables() defaults the has_index
+    //    to the field's index in the list of fields.
+    // 2. RepeatedFieldGenerator::RepeatedFieldGenerator() sets has_index to
+    //    GPBNoHasBit because repeated fields & map<> fields don't use the has
+    //    bit.
+    // 3. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+    //    index that groups all the elements on of the oneof.
+    // So in has_storage, we need enough bits for the single fields that aren't
+    // in any oneof, and then one int32 for each oneof (to store the field
+    // number).  So we could save a little space by not using the field's index
+    // and instead make a second pass only assigning indexes for the fields
+    // that would need it.  The only savings would come when messages have over
+    // a multiple of 32 fields with some number being repeated or in oneofs to
+    // drop the count below that 32 multiple; so it hasn't seemed worth doing
+    // at the moment.
+    size_t num_has_bits = descriptor_->field_count();
+    size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+    // 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);
+    // Add an int32 for each oneof to store which is set.
+    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");
+
+    bool has_oneofs = oneof_generators_.size();
+    if (has_oneofs) {
+      printer->Print(
+          "    static GPBMessageOneofDescription oneofs[] = {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+           iter != oneof_generators_.end(); ++iter) {
+        (*iter)->GenerateDescription(printer);
+      }
+      printer->Outdent();
+      printer->Outdent();
+      printer->Outdent();
+      printer->Print(
+          "    };\n");
+    }
+
+    TextFormatDecodeData text_format_decode_data;
+    bool has_fields = descriptor_->field_count() > 0;
+    if (has_fields) {
+      // TODO(thomasvl): The plugin's FieldGenerator::GenerateFieldDescription()
+      // wraps the fieldOptions's value of this structure in an CPP gate so
+      // they can be compiled away; but that still results in a const char* in
+      // the structure for a NULL pointer for every message field.  If the
+      // fieldOptions are moved to a separate payload like the TextFormat extra
+      // data is, then it would shrink that static data shrinking the binaries
+      // a little more.
+      // TODO(thomasvl): proto3 syntax doens't need a defaultValue in the
+      // structure because primitive types are always zero.  If we add a second
+      // structure and a different initializer, we can avoid the wasted static
+      // storage for every field in a proto3 message.
+      printer->Print(
+          "    static GPBMessageFieldDescription fields[] = {\n");
+      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);
+        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");
+    }
+
+    bool has_enums = enum_generators_.size();
+    if (has_enums) {
+      printer->Print(
+          "    static GPBMessageEnumDescription enums[] = {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+           iter != enum_generators_.end(); ++iter) {
+        printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
+                       "name", (*iter)->name());
+      }
+      printer->Outdent();
+      printer->Outdent();
+      printer->Outdent();
+      printer->Print(
+          "    };\n");
+    }
+
+    bool has_extensions = sorted_extensions.size();
+    if (has_extensions) {
+      printer->Print(
+          "    static GPBExtensionRange ranges[] = {\n");
+      printer->Indent();
+      printer->Indent();
+      printer->Indent();
+      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->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";
+    vars["fields_count"] =
+        has_fields ? "sizeof(fields) / sizeof(GPBMessageFieldDescription)" : "0";
+    vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
+    vars["oneof_count"] =
+        has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
+    vars["enums"] = has_enums ? "enums" : "NULL";
+    vars["enum_count"] =
+        has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
+    vars["ranges"] = has_extensions ? "ranges" : "NULL";
+    vars["range_count"] =
+        has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
+    vars["wireformat"] =
+        descriptor_->options().message_set_wire_format() ? "YES" : "NO";
+
+    if (text_format_decode_data.num_entries() == 0) {
+      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"
+          "                                        oneofs:$oneofs$\n"
+          "                                    oneofCount:$oneof_count$\n"
+          "                                         enums:$enums$\n"
+          "                                     enumCount:$enum_count$\n"
+          "                                        ranges:$ranges$\n"
+          "                                    rangeCount:$range_count$\n"
+          "                                   storageSize:sizeof($classname$__storage_)\n"
+          "                                    wireFormat:$wireformat$];\n");
+    } else {
+      vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
+      printer->Print(
+          vars,
+          "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+          "    const char *extraTextFormatInfo = NULL;\n"
+          "#else\n"
+          "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+          "#endif  // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+          "    GPBDescriptor *localDescriptor =\n"
+          "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+          "                                     rootClass:[$rootclassname$ class]\n"
+          "                                          file:$rootclassname$_FileDescriptor()\n"
+          "                                        fields:$fields$\n"
+          "                                    fieldCount:$fields_count$\n"
+          "                                        oneofs:$oneofs$\n"
+          "                                    oneofCount:$oneof_count$\n"
+          "                                         enums:$enums$\n"
+          "                                     enumCount:$enum_count$\n"
+          "                                        ranges:$ranges$\n"
+          "                                    rangeCount:$range_count$\n"
+          "                                   storageSize:sizeof($classname$__storage_)\n"
+          "                                    wireFormat:$wireformat$\n"
+          "                           extraTextFormatInfo:extraTextFormatInfo];\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/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
new file mode 100644
index 0000000..06b536f
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.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_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);
+  ~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/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
new file mode 100644
index 0000000..f2ce4e5
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -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.
+
+#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)
+    : ObjCObjFieldGenerator(descriptor) {
+  SetMessageVariables(descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+void MessageFieldGenerator::DetermineForwardDeclarations(
+    set<string>* fwd_decls) const {
+  // 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)
+    : RepeatedFieldGenerator(descriptor) {
+  SetMessageVariables(descriptor, &variables_);
+  variables_["array_storage_type"] = "NSMutableArray";
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
new file mode 100644
index 0000000..708ea56
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -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.
+
+#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);
+
+ protected:
+  explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  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);
+
+ protected:
+  explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~RepeatedMessageFieldGenerator();
+
+ 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/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
new file mode 100644
index 0000000..3cb8748
--- /dev/null
+++ b/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_,
+      "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, 0);\n"
+      "}\n");
+}
+
+void OneofGenerator::GenerateDescription(io::Printer* printer) {
+  printer->Print(
+      variables_,
+      "{\n"
+      "  .name = \"$name$\",\n"
+      "  .index = $index$,\n"
+      "},\n");
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
new file mode 100644
index 0000000..bcba82d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -0,0 +1,77 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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);
+  void GenerateDescription(io::Printer* printer);
+
+ 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/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
new file mode 100644
index 0000000..c185b66
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.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 <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;
+  }
+
+  // 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:
+      return "";  // Want NSArray
+  }
+
+  // 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)
+    : SingleFieldGenerator(descriptor) {
+  SetPrimitiveVariables(descriptor, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
+    const FieldDescriptor* descriptor)
+    : ObjCObjFieldGenerator(descriptor) {
+  SetPrimitiveVariables(descriptor, &variables_);
+  variables_["property_storage_attribute"] = "copy";
+}
+
+PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+    const FieldDescriptor* descriptor)
+    : RepeatedFieldGenerator(descriptor) {
+  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";
+  }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
+  RepeatedFieldGenerator::FinishInitialization();
+  if (IsPrimitiveType(descriptor_)) {
+    // No comment needed for primitive types.
+    variables_["array_comment"] = "";
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
new file mode 100644
index 0000000..9bb7934
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.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.
+
+#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);
+
+ protected:
+  explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~PrimitiveFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+  explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~PrimitiveObjFieldGenerator();
+
+ private:
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
+  friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+  explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+  virtual ~RepeatedPrimitiveFieldGenerator();
+  virtual void FinishInitialization(void);
+
+ 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/google/protobuf/compiler/package_info.h b/src/google/protobuf/compiler/package_info.h
new file mode 100644
index 0000000..fb6b473
--- /dev/null
+++ b/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/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
new file mode 100644
index 0000000..90ded4d
--- /dev/null
+++ b/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/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
new file mode 100644
index 0000000..2c561c2
--- /dev/null
+++ b/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/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
new file mode 100644
index 0000000..1d623dd
--- /dev/null
+++ b/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/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
new file mode 100644
index 0000000..2bebf1f
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.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: 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_;
+};
+
+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;
+  }
+
+  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 1;
+    }
+  }
+
+  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) {
+      std::cerr << argv[0] << ": protoc asked plugin to generate a file but "
+                              "did not provide a descriptor for the file: "
+                << request.file_to_generate(i) << std::endl;
+      return 1;
+    }
+  }
+
+  CodeGeneratorResponse response;
+  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;
+      }
+    }
+  }
+
+  if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) {
+    std::cerr << argv[0] << ": Error writing to stdout." << std::endl;
+    return 1;
+  }
+
+  return 0;
+}
+
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
new file mode 100644
index 0000000..679f9bd
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.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)
+//
+// 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.
+//
+// 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 <google/protobuf/stubs/common.h>
+namespace google {
+namespace protobuf {
+namespace compiler {
+
+class CodeGenerator;    // code_generator.h
+
+// Implements main() for a protoc plugin exposing the given code generator.
+LIBPROTOC_EXPORT int PluginMain(int argc, char* argv[], const CodeGenerator* generator);
+
+}  // namespace compiler
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
new file mode 100644
index 0000000..a2da8ee
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -0,0 +1,1570 @@
+// 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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorRequest* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorResponse_File* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse_File::CopyFrom(const CodeGeneratorResponse_File& from) {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const CodeGeneratorResponse* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void CodeGeneratorResponse::CopyFrom(const CodeGeneratorResponse& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
new file mode 100644
index 0000000..0a03e97
--- /dev/null
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -0,0 +1,812 @@
+// 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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
new file mode 100644
index 0000000..acaee1f
--- /dev/null
+++ b/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/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc
new file mode 100644
index 0000000..4d500f9
--- /dev/null
+++ b/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 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 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/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
new file mode 100644
index 0000000..aa0f5fc
--- /dev/null
+++ b/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/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
new file mode 100644
index 0000000..e82bbae
--- /dev/null
+++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc
@@ -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: 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/googletest.h>
+#include <gtest/gtest.h>
+#include <google/protobuf/testing/file.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/google/protobuf/compiler/ruby/ruby_generated_code.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
new file mode 100644
index 0000000..42d82a6
--- /dev/null
+++ b/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/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb
new file mode 100644
index 0000000..49b23fb
--- /dev/null
+++ b/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/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
new file mode 100644
index 0000000..9692f1b
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -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.
+
+#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 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");
+  }
+}
+
+void GenerateFile(const google::protobuf::FileDescriptor* file,
+                  google::protobuf::io::Printer* printer) {
+  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++) {
+    const std::string& name = file->dependency(i)->name();
+    printer->Print(
+      "require '$name$'\n", "name", StripDotProto(name));
+  }
+
+  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);
+}
+
+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;
+  }
+
+  std::string filename =
+      StripDotProto(file->name()) + ".rb";
+  scoped_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '$');
+
+  GenerateFile(file, &printer);
+
+  return true;
+}
+
+}  // namespace ruby
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
new file mode 100644
index 0000000..75555c3
--- /dev/null
+++ b/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/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
new file mode 100644
index 0000000..1b04cb3
--- /dev/null
+++ b/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/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
new file mode 100644
index 0000000..a30ac30
--- /dev/null
+++ b/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 = 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/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
new file mode 100644
index 0000000..2513863
--- /dev/null
+++ b/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/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc
new file mode 100644
index 0000000..4830fd7
--- /dev/null
+++ b/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/google/protobuf/compiler/zip_output_unittest.sh b/src/google/protobuf/compiler/zip_output_unittest.sh
new file mode 100755
index 0000000..6fc7136
--- /dev/null
+++ b/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/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
new file mode 100644
index 0000000..458cced
--- /dev/null
+++ b/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/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
new file mode 100644
index 0000000..602e508
--- /dev/null
+++ b/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/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
new file mode 100644
index 0000000..78a3461
--- /dev/null
+++ b/src/google/protobuf/descriptor.cc
@@ -0,0 +1,6267 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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>;
+  allowed_proto3_extendees_->insert("google.protobuf.FileOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.MessageOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.FieldOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.EnumOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.EnumValueOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.ServiceOptions");
+  allowed_proto3_extendees_->insert("google.protobuf.MethodOptions");
+  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;
+
+  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();
+  }
+
+  // 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));
+  }
+  if (IsLite(file)) {
+    AddError(file->name(), proto,
+             DescriptorPool::ErrorCollector::OTHER,
+             "Lite runtime is not supported in proto3.");
+  }
+}
+
+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/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
new file mode 100644
index 0000000..7e3a749
--- /dev/null
+++ b/src/google/protobuf/descriptor.h
@@ -0,0 +1,1886 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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
+
+// 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;
+
+  // 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;
+
+  // 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:
+  // 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;
+
+  // 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;
+
+  // 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;
+
+  // 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;
+
+  // 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/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
new file mode 100644
index 0000000..ff0cfcf
--- /dev/null
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -0,0 +1,14926 @@
+// 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_[16] = {
+    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, javanano_use_deprecated_package_),
+    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\"\256\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\022+\n\037javana"
+    "no_use_deprecated_package\030& \001(\010B\002\030\001\022C\n\024u"
+    "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+    "obuf.UninterpretedOption\":\n\014OptimizeMode"
+    "\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTI"
+    "ME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027me"
+    "ssage_set_wire_format\030\001 \001(\010:\005false\022.\n\037no"
+    "_standard_descriptor_accessor\030\002 \001(\010:\005fal"
+    "se\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_ent"
+    "ry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
+    "$.google.protobuf.UninterpretedOption*\t\010"
+    "\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\016"
+    "2#.google.protobuf.FieldOptions.CType:\006S"
+    "TRING\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\ndeprecate"
+    "d\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024u"
+    "ninterpreted_option\030\347\007 \003(\0132$.google.prot"
+    "obuf.UninterpretedOption\"/\n\005CType\022\n\n\006STR"
+    "ING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002\"5\n\006JST"
+    "ype\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\013a"
+    "llow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fa"
+    "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
+    "gle.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\ndeprecat"
+    "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030"
+    "\347\007 \003(\0132$.google.protobuf.UninterpretedOp"
+    "tion*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndepr"
+    "ecated\030! \001(\010:\005false\022C\n\024uninterpreted_opt"
+    "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret"
+    "edOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOpt"
+    "ion\022;\n\004name\030\002 \003(\0132-.google.protobuf.Unin"
+    "terpretedOption.NamePart\022\030\n\020identifier_v"
+    "alue\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_val"
+    "ue\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggreg"
+    "ate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part"
+    "\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceC"
+    "odeInfo\022:\n\010location\030\001 \003(\0132(.google.proto"
+    "buf.SourceCodeInfo.Location\032\206\001\n\010Location"
+    "\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\020"
+    "leading_comments\030\003 \001(\t\022\031\n\021trailing_comme"
+    "nts\030\004 \001(\t\022!\n\031leading_detached_comments\030\006"
+    " \003(\t\"\247\001\n\021GeneratedCodeInfo\022A\n\nannotation"
+    "\030\001 \003(\0132-.google.protobuf.GeneratedCodeIn"
+    "fo.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\020D"
+    "escriptorProtosH\001Z\ndescriptor\242\002\003GPB\252\002\032Go"
+    "ogle.Protobuf.Reflection", 5184);
+  ::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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileDescriptorSet* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<DescriptorProto_ExtensionRange*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto_ExtensionRange* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto_ExtensionRange::CopyFrom(const DescriptorProto_ExtensionRange& from) {
+  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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<DescriptorProto_ReservedRange*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto_ReservedRange* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void DescriptorProto::MergeFrom(const DescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DescriptorProto::CopyFrom(const DescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldDescriptorProto::CopyFrom(const FieldDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const OneofDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValueDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValueDescriptorProto::CopyFrom(const EnumValueDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ServiceDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MethodDescriptorProto*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MethodDescriptorProto* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MethodDescriptorProto::CopyFrom(const MethodDescriptorProto& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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::kJavananoUseDeprecatedPackageFieldNumber;
+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());
+  javanano_use_deprecated_package_ = false;
+  ::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() {
+  _extensions_.Clear();
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FileOptions*>(16)->f)
+
+#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] & 32512u) {
+    ZR_(java_generic_services_, javanano_use_deprecated_package_);
+    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 (!(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(304)) goto parse_javanano_use_deprecated_package;
+        break;
+      }
+
+      // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+      case 38: {
+        if (tag == 304) {
+         parse_javanano_use_deprecated_package:
+          DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<
+                   bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>(
+                 input, &javanano_use_deprecated_package_)));
+          set_has_javanano_use_deprecated_package();
+        } 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);
+  }
+
+  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+  if (has_javanano_use_deprecated_package()) {
+    ::google::protobuf::internal::WireFormatLite::WriteBool(38, this->javanano_use_deprecated_package(), 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);
+  }
+
+  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+  if (has_javanano_use_deprecated_package()) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(38, this->javanano_use_deprecated_package(), 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 {
+  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] & 32512u) {
+    // 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());
+    }
+
+    // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+    if (has_javanano_use_deprecated_package()) {
+      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 FileOptions::MergeFrom(const ::google::protobuf::Message& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FileOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FileOptions::MergeFrom(const FileOptions& from) {
+  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_);
+    }
+    if (from.has_javanano_use_deprecated_package()) {
+      set_javanano_use_deprecated_package(from.javanano_use_deprecated_package());
+    }
+  }
+  _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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FileOptions::CopyFrom(const FileOptions& from) {
+  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_);
+  std::swap(javanano_use_deprecated_package_, other->javanano_use_deprecated_package_);
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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)
+}
+
+// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+bool FileOptions::has_javanano_use_deprecated_package() const {
+  return (_has_bits_[0] & 0x00004000u) != 0;
+}
+void FileOptions::set_has_javanano_use_deprecated_package() {
+  _has_bits_[0] |= 0x00004000u;
+}
+void FileOptions::clear_has_javanano_use_deprecated_package() {
+  _has_bits_[0] &= ~0x00004000u;
+}
+void FileOptions::clear_javanano_use_deprecated_package() {
+  javanano_use_deprecated_package_ = false;
+  clear_has_javanano_use_deprecated_package();
+}
+ bool FileOptions::javanano_use_deprecated_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
+  return javanano_use_deprecated_package_;
+}
+ void FileOptions::set_javanano_use_deprecated_package(bool value) {
+  set_has_javanano_use_deprecated_package();
+  javanano_use_deprecated_package_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
+}
+
+// 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() {
+  _extensions_.Clear();
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<MessageOptions*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MessageOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void MessageOptions::MergeFrom(const MessageOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MessageOptions::CopyFrom(const MessageOptions& from) {
+  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() {
+  _extensions_.Clear();
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<FieldOptions*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FieldOptions::MergeFrom(const FieldOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldOptions::CopyFrom(const FieldOptions& from) {
+  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() {
+  _extensions_.Clear();
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<EnumOptions*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void EnumOptions::MergeFrom(const EnumOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumOptions::CopyFrom(const EnumOptions& from) {
+  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() {
+  _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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValueOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void EnumValueOptions::MergeFrom(const EnumValueOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValueOptions::CopyFrom(const EnumValueOptions& from) {
+  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() {
+  _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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ServiceOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void ServiceOptions::MergeFrom(const ServiceOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ServiceOptions::CopyFrom(const ServiceOptions& from) {
+  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() {
+  _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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const MethodOptions* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void MethodOptions::MergeFrom(const MethodOptions& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void MethodOptions::CopyFrom(const MethodOptions& from) {
+  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() {
+  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 (!(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 {
+  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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UninterpretedOption_NamePart* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UninterpretedOption_NamePart::CopyFrom(const UninterpretedOption_NamePart& from) {
+  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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<UninterpretedOption*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UninterpretedOption* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void UninterpretedOption::MergeFrom(const UninterpretedOption& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UninterpretedOption::CopyFrom(const UninterpretedOption& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceCodeInfo_Location* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo_Location::CopyFrom(const SourceCodeInfo_Location& from) {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceCodeInfo* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceCodeInfo::CopyFrom(const SourceCodeInfo& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<GeneratedCodeInfo_Annotation*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const GeneratedCodeInfo_Annotation* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GeneratedCodeInfo_Annotation::CopyFrom(const GeneratedCodeInfo_Annotation& from) {
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const GeneratedCodeInfo* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void GeneratedCodeInfo::CopyFrom(const GeneratedCodeInfo& from) {
+  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() {
+  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/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
new file mode 100644
index 0000000..3fe07bf
--- /dev/null
+++ b/src/google/protobuf/descriptor.pb.h
@@ -0,0 +1,7679 @@
+// 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);
+
+  // optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+  bool has_javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
+  void clear_javanano_use_deprecated_package() PROTOBUF_DEPRECATED;
+  static const int kJavananoUseDeprecatedPackageFieldNumber = 38;
+  bool javanano_use_deprecated_package() const PROTOBUF_DEPRECATED;
+  void set_javanano_use_deprecated_package(bool value) PROTOBUF_DEPRECATED;
+
+  // 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();
+  inline void set_has_javanano_use_deprecated_package();
+  inline void clear_has_javanano_use_deprecated_package();
+
+  ::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_;
+  bool java_generic_services_;
+  bool py_generic_services_;
+  bool deprecated_;
+  bool cc_enable_arenas_;
+  bool javanano_use_deprecated_package_;
+  ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_;
+  ::google::protobuf::internal::ArenaStringPtr csharp_namespace_;
+  ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_;
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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)
+}
+
+// optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+inline bool FileOptions::has_javanano_use_deprecated_package() const {
+  return (_has_bits_[0] & 0x00004000u) != 0;
+}
+inline void FileOptions::set_has_javanano_use_deprecated_package() {
+  _has_bits_[0] |= 0x00004000u;
+}
+inline void FileOptions::clear_has_javanano_use_deprecated_package() {
+  _has_bits_[0] &= ~0x00004000u;
+}
+inline void FileOptions::clear_javanano_use_deprecated_package() {
+  javanano_use_deprecated_package_ = false;
+  clear_has_javanano_use_deprecated_package();
+}
+inline bool FileOptions::javanano_use_deprecated_package() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.javanano_use_deprecated_package)
+  return javanano_use_deprecated_package_;
+}
+inline void FileOptions::set_javanano_use_deprecated_package(bool value) {
+  set_has_javanano_use_deprecated_package();
+  javanano_use_deprecated_package_ = value;
+  // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.javanano_use_deprecated_package)
+}
+
+// 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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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() {
+  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/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
new file mode 100644
index 0000000..3e664d5
--- /dev/null
+++ b/src/google/protobuf/descriptor.proto
@@ -0,0 +1,805 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+
+  // Whether the nano proto compiler should generate in the deprecated non-nano
+  // suffixed package.
+  optional bool javanano_use_deprecated_package = 38 [deprecated = true];
+
+  // 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 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/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
new file mode 100644
index 0000000..2117c02
--- /dev/null
+++ b/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/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
new file mode 100644
index 0000000..86002d5
--- /dev/null
+++ b/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/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
new file mode 100644
index 0000000..1fc3816
--- /dev/null
+++ b/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/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
new file mode 100644
index 0000000..be8e0b7
--- /dev/null
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -0,0 +1,6624 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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, ValidateProto3LiteRuntime) {
+  // Lite runtime is not supported in proto3.
+  BuildFileWithErrors(
+      "name: 'foo.proto' "
+      "syntax: 'proto3' "
+      "options { "
+      "  optimize_for: LITE_RUNTIME "
+      "} ",
+      "foo.proto: foo.proto: OTHER: Lite runtime is not supported "
+      "in proto3.\n");
+}
+
+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/google/protobuf/drop_unknown_fields_test.cc b/src/google/protobuf/drop_unknown_fields_test.cc
new file mode 100644
index 0000000..6f16dc5
--- /dev/null
+++ b/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/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
new file mode 100644
index 0000000..b325944
--- /dev/null
+++ b/src/google/protobuf/duration.pb.cc
@@ -0,0 +1,408 @@
+// 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(\005BP\n\023com.google.protobufB\rDu"
+    "rationProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Protobuf"
+    ".WellKnownTypesb\006proto3", 183);
+  ::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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Duration*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Duration* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Duration>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Duration::MergeFrom(const Duration& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Duration::CopyFrom(const Duration& from) {
+  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/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
new file mode 100644
index 0000000..215a52c
--- /dev/null
+++ b/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/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
new file mode 100644
index 0000000..78bcc74
--- /dev/null
+++ b/src/google/protobuf/duration.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 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/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
new file mode 100644
index 0000000..8d689ac
--- /dev/null
+++ b/src/google/protobuf/dynamic_message.cc
@@ -0,0 +1,862 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+
+
+ 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*>(
+                      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) {
+            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, 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, 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/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
new file mode 100644
index 0000000..f74cd7d
--- /dev/null
+++ b/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/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
new file mode 100644
index 0000000..70e437d
--- /dev/null
+++ b/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/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
new file mode 100644
index 0000000..f2eec78
--- /dev/null
+++ b/src/google/protobuf/empty.pb.cc
@@ -0,0 +1,310 @@
+// 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\005EmptyBP\n\023com.google.protobufB\n"
+    "EmptyProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Protob"
+    "uf.WellKnownTypesb\006proto3", 145);
+  ::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() {
+}
+
+bool Empty::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Empty* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Empty>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Empty::MergeFrom(const Empty& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+}
+
+void Empty::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Empty::CopyFrom(const Empty& from) {
+  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/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
new file mode 100644
index 0000000..868009f
--- /dev/null
+++ b/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/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
new file mode 100644
index 0000000..b96daf2
--- /dev/null
+++ b/src/google/protobuf/empty.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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+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/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
new file mode 100644
index 0000000..9afb236
--- /dev/null
+++ b/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/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
new file mode 100644
index 0000000..bca179b
--- /dev/null
+++ b/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/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
new file mode 100644
index 0000000..82e3e09
--- /dev/null
+++ b/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/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
new file mode 100644
index 0000000..f40fcbc
--- /dev/null
+++ b/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/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
new file mode 100644
index 0000000..01a6ce5
--- /dev/null
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -0,0 +1,396 @@
+// 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() {
+  paths_.Clear();
+}
+
+bool FieldMask::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FieldMask* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FieldMask::MergeFrom(const FieldMask& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  paths_.MergeFrom(from.paths_);
+}
+
+void FieldMask::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FieldMask::CopyFrom(const FieldMask& from) {
+  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() {
+  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/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
new file mode 100644
index 0000000..7189fd7
--- /dev/null
+++ b/src/google/protobuf/field_mask.pb.h
@@ -0,0 +1,201 @@
+// 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() {
+  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/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
new file mode 100644
index 0000000..908c8a8
--- /dev/null
+++ b/src/google/protobuf/field_mask.proto
@@ -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.
+
+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 applies 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"
+//     }
+//
+message FieldMask {
+  // The set of field mask paths.
+  repeated string paths = 1;
+}
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
new file mode 100644
index 0000000..fdcdc27
--- /dev/null
+++ b/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/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h
new file mode 100644
index 0000000..e424205
--- /dev/null
+++ b/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/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
new file mode 100644
index 0000000..eee024e
--- /dev/null
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -0,0 +1,2274 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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:
+      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:
+        std::swap(*MutableRaw<Message*>(message1, field),
+                  *MutableRaw<Message*>(message2, field));
+        break;
+
+      case FieldDescriptor::CPPTYPE_STRING:
+        switch (field->options().ctype()) {
+          default:  // TODO(kenton):  Support other string reps.
+          case FieldOptions::STRING:
+            MutableRaw<ArenaStringPtr>(message1, field)->Swap(
+                MutableRaw<ArenaStringPtr>(message2, field));
+            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)->InsertMapValue(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/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h
new file mode 100644
index 0000000..9ef7871
--- /dev/null
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -0,0 +1,673 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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.
+//
+// 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))
+
+#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/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
new file mode 100644
index 0000000..85ebdef
--- /dev/null
+++ b/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/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
new file mode 100644
index 0000000..7b813f8
--- /dev/null
+++ b/src/google/protobuf/generated_message_util.cc
@@ -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)
+//  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);
+}
+
+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/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h
new file mode 100644
index 0000000..78c8d7f
--- /dev/null
+++ b/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
+
+
+// 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 inline const ::std::string& GetEmptyString() {
+  ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString);
+  return GetEmptyStringAlreadyInited();
+}
+
+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/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
new file mode 100644
index 0000000..e3a34d0
--- /dev/null
+++ b/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 = 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_ = 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_ = 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 = 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 = 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/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h
new file mode 100644
index 0000000..e377100
--- /dev/null
+++ b/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 = 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/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h
new file mode 100644
index 0000000..d95b06e
--- /dev/null
+++ b/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/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
new file mode 100644
index 0000000..d1782e3
--- /dev/null
+++ b/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/scoped_ptr.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/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc
new file mode 100644
index 0000000..1be6c86
--- /dev/null
+++ b/src/google/protobuf/io/gzip_stream.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: 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();
+  if (input_buffer_ != NULL) {
+    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/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
new file mode 100644
index 0000000..8244500
--- /dev/null
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -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: 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 <zlib.h>
+
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/io/zero_copy_stream.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/google/protobuf/io/gzip_stream_unittest.sh b/src/google/protobuf/io/gzip_stream_unittest.sh
new file mode 100755
index 0000000..16251a9
--- /dev/null
+++ b/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/google/protobuf/io/package_info.h b/src/google/protobuf/io/package_info.h
new file mode 100644
index 0000000..dc1fc91
--- /dev/null
+++ b/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/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
new file mode 100644
index 0000000..7d88650
--- /dev/null
+++ b/src/google/protobuf/io/printer.cc
@@ -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.
+
+// 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),
+    at_start_of_line_(true),
+    failed_(false) {
+}
+
+Printer::~Printer() {
+  // Only BackUp() if we have called Next() at least once and never failed.
+  if (buffer_size_ > 0 && !failed_) {
+    output_->BackUp(buffer_size_);
+  }
+}
+
+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.
+
+  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 {
+          WriteRaw(iter->second.data(), iter->second.size());
+        }
+      }
+
+      // 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_);
+    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;
+}
+
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
new file mode 100644
index 0000000..f1490bb
--- /dev/null
+++ b/src/google/protobuf/io/printer.h
@@ -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: 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 <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+
+class ZeroCopyOutputStream;     // zero_copy_stream.h
+
+// 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.
+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);
+  ~Printer();
+
+  // 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:
+  const char variable_delimiter_;
+
+  ZeroCopyOutputStream* const output_;
+  char* buffer_;
+  int buffer_size_;
+
+  string indent_;
+  bool at_start_of_line_;
+  bool failed_;
+
+  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
+};
+
+}  // namespace io
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_IO_PRINTER_H__
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
new file mode 100644
index 0000000..258dd98
--- /dev/null
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -0,0 +1,286 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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);
+}
+
+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");
+}
+#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/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc
new file mode 100644
index 0000000..a90bb9a
--- /dev/null
+++ b/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/google/protobuf/io/strtod.h b/src/google/protobuf/io/strtod.h
new file mode 100644
index 0000000..f56e41c
--- /dev/null
+++ b/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/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
new file mode 100644
index 0000000..3d57707
--- /dev/null
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -0,0 +1,1137 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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);
+    GOOGLE_LOG_IF(DFATAL, digit < 0 || digit >= base)
+      << " Tokenizer::ParseInteger() passed text that could not have been"
+         " tokenized as an integer: " << CEscape(text);
+    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/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
new file mode 100644
index 0000000..49885ed
--- /dev/null
+++ b/src/google/protobuf/io/tokenizer.h
@@ -0,0 +1,403 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+
+// 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, int 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 */, int /* 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;
+    int column;
+    int 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_;
+  int 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.
+  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/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
new file mode 100644
index 0000000..20d50a2
--- /dev/null
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -0,0 +1,1002 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+#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::ParseInteger("zxy", kuint64max, &i),
+    "passed text that could not have been tokenized as an integer");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("1.2", kuint64max, &i),
+    "passed text that could not have been tokenized as an integer");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("08", kuint64max, &i),
+    "passed text that could not have been tokenized as an integer");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("0xg", kuint64max, &i),
+    "passed text that could not have been tokenized as an integer");
+  EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i),
+    "passed text that could not have been tokenized as an integer");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
+  // 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/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
new file mode 100644
index 0000000..186de00
--- /dev/null
+++ b/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/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h
new file mode 100644
index 0000000..52650fc
--- /dev/null
+++ b/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/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
new file mode 100644
index 0000000..7ec2b5d
--- /dev/null
+++ b/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/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
new file mode 100644
index 0000000..0746fa6
--- /dev/null
+++ b/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/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
new file mode 100644
index 0000000..083beca
--- /dev/null
+++ b/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_ = 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_ = 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_NE(NULL, target_);
+  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_,
+      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_NE(NULL, target_);
+  GOOGLE_CHECK_LE(count, target_->size());
+  target_->resize(target_->size() - count);
+}
+
+int64 StringOutputStream::ByteCount() const {
+  GOOGLE_CHECK_NE(NULL, target_);
+  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, 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/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
new file mode 100644
index 0000000..1c397de
--- /dev/null
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -0,0 +1,410 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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 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/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
new file mode 100644
index 0000000..8c7358c
--- /dev/null
+++ b/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/io/zero_copy_stream_impl.h>
+#include <google/protobuf/io/coded_stream.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/stubs/scoped_ptr.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/google/protobuf/lite_arena_unittest.cc b/src/google/protobuf/lite_arena_unittest.cc
new file mode 100644
index 0000000..f0bee88
--- /dev/null
+++ b/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/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
new file mode 100644
index 0000000..d1948ab
--- /dev/null
+++ b/src/google/protobuf/lite_unittest.cc
@@ -0,0 +1,691 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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());
+  }
+
+  std::cout << "PASS" << std::endl;
+  return 0;
+}
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
new file mode 100644
index 0000000..dfc6242
--- /dev/null
+++ b/src/google/protobuf/map.h
@@ -0,0 +1,884 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 <iterator>
+#include <google/protobuf/stubs/hash.h>
+#include <limits>  // To support Visual Studio 2008
+
+#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>
+
+namespace google {
+namespace protobuf {
+
+template <typename Key, typename T>
+class Map;
+
+template <typename Enum> struct is_proto_enum;
+
+class MapIterator;
+
+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_) {
+      return false;
+    }
+    switch (type()) {
+      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_;
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Can't get here.";
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return false;
+  }
+
+  void CopyFrom(const MapKey& other) {
+    SetType(other.type());
+    switch (type_) {
+      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;
+      case FieldDescriptor::CPPTYPE_DOUBLE:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_MESSAGE:
+        GOOGLE_LOG(FATAL) << "Can't get here.";
+        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. Its interface is similar to std::unordered_map. Users should use this
+// interface directly to visit or change map fields.
+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;
+  typedef equal_to<Key> key_equal;
+
+  Map()
+      : arena_(NULL),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(0) {}
+  explicit Map(Arena* arena)
+      : arena_(arena),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(0) {
+    arena_->OwnDestructor(&elements_);
+  }
+
+  Map(const Map& other)
+      : arena_(NULL),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(other.default_enum_value_) {
+    insert(other.begin(), other.end());
+  }
+  template <class InputIt>
+  Map(const InputIt& first, const InputIt& last)
+      : arena_(NULL),
+        allocator_(arena_),
+        elements_(0, hasher(), key_equal(), allocator_),
+        default_enum_value_(0) {
+    insert(first, last);
+  }
+
+  ~Map() { clear(); }
+
+ private:
+  // 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)
+    template<class NodeType, class... Args>
+    void construct(NodeType* p, Args&&... args) {
+      new (static_cast<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;
+  };
+
+  typedef MapAllocator<std::pair<const Key, MapPair<Key, T>*> > Allocator;
+  typedef hash_map<Key, value_type*, hash<Key>, equal_to<Key>, Allocator>
+      InnerMap;
+
+ public:
+  // Iterators
+  class const_iterator
+      : public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
+                             const value_type*, const value_type&> {
+    typedef typename InnerMap::const_iterator InnerIt;
+
+   public:
+    const_iterator() {}
+    explicit const_iterator(const InnerIt& it) : it_(it) {}
+
+    const_reference operator*() const { return *it_->second; }
+    const_pointer operator->() const { return it_->second; }
+
+    const_iterator& operator++() {
+      ++it_;
+      return *this;
+    }
+    const_iterator operator++(int) { return const_iterator(it_++); }
+
+    friend bool operator==(const const_iterator& a, const const_iterator& b) {
+      return a.it_ == b.it_;
+    }
+    friend bool operator!=(const const_iterator& a, const const_iterator& b) {
+      return a.it_ != b.it_;
+    }
+
+   private:
+    InnerIt it_;
+  };
+
+  class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+    typedef typename InnerMap::iterator InnerIt;
+
+   public:
+    iterator() {}
+    explicit iterator(const InnerIt& it) : it_(it) {}
+
+    reference operator*() const { return *it_->second; }
+    pointer operator->() const { return it_->second; }
+
+    iterator& operator++() {
+      ++it_;
+      return *this;
+    }
+    iterator operator++(int) { return iterator(it_++); }
+
+    // Implicitly convertible to const_iterator.
+    operator const_iterator() const { return const_iterator(it_); }
+
+    friend bool operator==(const iterator& a, const iterator& b) {
+      return a.it_ == b.it_;
+    }
+    friend bool operator!=(const iterator& a, const iterator& b) {
+      return a.it_ != b.it_;
+    }
+
+   private:
+    friend class Map;
+    InnerIt it_;
+  };
+
+  iterator begin() { return iterator(elements_.begin()); }
+  iterator end() { return iterator(elements_.end()); }
+  const_iterator begin() const { return const_iterator(elements_.begin()); }
+  const_iterator end() const { return const_iterator(elements_.end()); }
+  const_iterator cbegin() const { return begin(); }
+  const_iterator cend() const { return end(); }
+
+  // Capacity
+  size_type size() const { return elements_.size(); }
+  bool empty() const { return elements_.empty(); }
+
+  // Element access
+  T& operator[](const key_type& key) {
+    value_type** value = &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 {
+    return elements_.count(key);
+  }
+  const_iterator find(const key_type& key) const {
+    return const_iterator(elements_.find(key));
+  }
+  iterator find(const key_type& key) {
+    return 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) {
+    iterator it = find(value.first);
+    if (it != end()) {
+      return std::pair<iterator, bool>(it, false);
+    } else {
+      return std::pair<iterator, bool>(
+          iterator(elements_.insert(std::pair<Key, value_type*>(
+              value.first, CreateValueTypeInternal(value))).first), true);
+    }
+  }
+  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
+  size_type erase(const key_type& key) {
+    typename InnerMap::iterator it = elements_.find(key);
+    if (it == elements_.end()) {
+      return 0;
+    } else {
+      if (arena_ == NULL) delete it->second;
+      elements_.erase(it);
+      return 1;
+    }
+  }
+  void erase(iterator pos) {
+    if (arena_ == NULL) delete pos.it_->second;
+    elements_.erase(pos.it_);
+  }
+  void erase(iterator first, iterator last) {
+    for (iterator it = first; it != last;) {
+      if (arena_ == NULL) delete it.it_->second;
+      elements_.erase((it++).it_);
+    }
+  }
+  void clear() {
+    for (iterator it = begin(); it != end(); ++it) {
+      if (arena_ == NULL) delete it.it_->second;
+    }
+    elements_.clear();
+  }
+
+  // Assign
+  Map& operator=(const Map& other) {
+    if (this != &other) {
+      clear();
+      insert(other.begin(), other.end());
+    }
+    return *this;
+  }
+
+ 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_;
+  Allocator allocator_;
+  InnerMap elements_;
+  int default_enum_value_;
+
+  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_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());
+      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.";
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return 0;
+  }
+  bool
+  operator()(const google::protobuf::MapKey& map_key1,
+             const google::protobuf::MapKey& map_key2) const {
+    switch (map_key1.type()) {
+#define COMPARE_CPPTYPE(CPPTYPE, CPPTYPE_METHOD)             \
+      case google::protobuf::FieldDescriptor::CPPTYPE_##CPPTYPE: \
+        return map_key1.Get##CPPTYPE_METHOD##Value() <           \
+               map_key2.Get##CPPTYPE_METHOD##Value();
+      COMPARE_CPPTYPE(STRING, String)
+      COMPARE_CPPTYPE(INT64,  Int64)
+      COMPARE_CPPTYPE(INT32,  Int32)
+      COMPARE_CPPTYPE(UINT64, UInt64)
+      COMPARE_CPPTYPE(UINT32, UInt32)
+      COMPARE_CPPTYPE(BOOL,   Bool)
+#undef COMPARE_CPPTYPE
+      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.";
+    }
+    GOOGLE_LOG(FATAL) << "Can't get here.";
+    return true;
+  }
+};
+GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
+
+#endif  // GOOGLE_PROTOBUF_MAP_H__
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
new file mode 100644
index 0000000..987c4e2
--- /dev/null
+++ b/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/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
new file mode 100644
index 0000000..7cdf1b9
--- /dev/null
+++ b/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/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
new file mode 100644
index 0000000..eddc95c
--- /dev/null
+++ b/src/google/protobuf/map_field.cc
@@ -0,0 +1,466 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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::InsertMapValue(
+    const MapKey& map_key, MapValueRef* val) {
+  bool result = false;
+
+  MapValueRef& map_val = (*MutableMap())[map_key];
+  // If map_val.data_ is not set, it is newly inserted by map_[map_key].
+  if (map_val.data_ == NULL) {
+    result = true;
+    const FieldDescriptor* val_des =
+        default_entry_->GetDescriptor()->FindFieldByName("value");
+    map_val.SetType(val_des->cpp_type());
+    // Allocate momery 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 result;
+}
+
+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/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
new file mode 100644
index 0000000..9130166
--- /dev/null
+++ b/src/google/protobuf/map_field.h
@@ -0,0 +1,396 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 InsertMapValue(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 InsertMapValue(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 InsertMapValue(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/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h
new file mode 100644
index 0000000..f116697
--- /dev/null
+++ b/src/google/protobuf/map_field_inl.h
@@ -0,0 +1,483 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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>::InsertMapValue(const MapKey& map_key,
+                                                  MapValueRef* val) {
+  Map<Key, T>* map = MutableMap();
+  bool result = false;
+  const Key& key = UnwrapMapKey<Key>(map_key);
+  if (map->end() == map->find(key)) {
+    result = true;
+  }
+  val->SetValue(&((*map)[key]));
+  return result;
+}
+
+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/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
new file mode 100644
index 0000000..860dae5
--- /dev/null
+++ b/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/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
new file mode 100644
index 0000000..2ff1d6b
--- /dev/null
+++ b/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 InsertMapValue(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/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc
new file mode 100644
index 0000000..b65b4d6
--- /dev/null
+++ b/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/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h
new file mode 100644
index 0000000..66dedde
--- /dev/null
+++ b/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/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto
new file mode 100644
index 0000000..0592dd7
--- /dev/null
+++ b/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/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
new file mode 100644
index 0000000..916cc54
--- /dev/null
+++ b/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/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
new file mode 100644
index 0000000..451b02e
--- /dev/null
+++ b/src/google/protobuf/map_test.cc
@@ -0,0 +1,2469 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 <sstream>
+
+#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/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 =====================================================
+
+class MapImplTest : public ::testing::Test {
+ protected:
+  MapImplTest()
+      : map_ptr_(new Map<int32, int32>),
+        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_F(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_F(MapImplTest, OperatorBracketNonExist) {
+  int32 key = 0;
+  int32 default_value = 0;
+
+  EXPECT_EQ(default_value, map_[key]);
+  ExpectSingleElement(key, default_value);
+}
+
+TEST_F(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_F(MapImplTest, MutableAtNonExistDeathTest) {
+  EXPECT_DEATH(map_.at(0), "");
+}
+
+TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
+  EXPECT_DEATH(const_map_.at(0), "");
+}
+
+TEST_F(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_F(MapImplTest, CountNonExist) {
+  EXPECT_EQ(0, map_.count(0));
+}
+
+TEST_F(MapImplTest, MutableFindNonExist) {
+  EXPECT_TRUE(map_.end() == map_.find(0));
+}
+
+TEST_F(MapImplTest, ImmutableFindNonExist) {
+  EXPECT_TRUE(const_map_.end() == const_map_.find(0));
+}
+
+TEST_F(MapImplTest, ConstEnd) {
+  EXPECT_TRUE(const_map_.end() == const_map_.cend());
+}
+
+TEST_F(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_F(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 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_F(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_F(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_F(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_F(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_F(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_F(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_F(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_F(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_F(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_F(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());
+}
+
+TEST_F(MapImplTest, CopyConstructor) {
+  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(map_);
+
+  EXPECT_EQ(2, other.size());
+  EXPECT_EQ(value1, other.at(key1));
+  EXPECT_EQ(value2, other.at(key2));
+}
+
+TEST_F(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());
+
+  EXPECT_EQ(2, new_map.size());
+  EXPECT_EQ(value1, new_map.at(key1));
+  EXPECT_EQ(value2, new_map.at(key2));
+}
+
+TEST_F(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;
+  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));
+}
+
+TEST_F(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_F(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_F(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_F(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);
+}
+
+// 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/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
new file mode 100644
index 0000000..ae09464
--- /dev/null
+++ b/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/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
new file mode 100644
index 0000000..deaf0f4
--- /dev/null
+++ b/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/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
new file mode 100644
index 0000000..b3ba4e0
--- /dev/null
+++ b/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/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
new file mode 100644
index 0000000..f8ad758
--- /dev/null
+++ b/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/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
new file mode 100644
index 0000000..aea1e8c
--- /dev/null
+++ b/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/google/protobuf/map_unittest_proto3.proto b/src/google/protobuf/map_unittest_proto3.proto
new file mode 100644
index 0000000..16be277
--- /dev/null
+++ b/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/google/protobuf/message.cc b/src/google/protobuf/message.cc
new file mode 100644
index 0000000..032748b
--- /dev/null
+++ b/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/google/protobuf/message.h b/src/google/protobuf/message.h
new file mode 100644
index 0000000..a4d9277
--- /dev/null
+++ b/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/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
new file mode 100644
index 0000000..5bd8bcf
--- /dev/null
+++ b/src/google/protobuf/message_lite.cc
@@ -0,0 +1,365 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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) {
+  GOOGLE_CHECK_EQ(byte_size_before_serialization, byte_size_after_serialization)
+      << "Protocol message 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 the message.";
+  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);
+    }
+    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);
+    }
+
+    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);
+  }
+  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);
+  }
+  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);
+}
+}  // namespace internal
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
new file mode 100644
index 0000000..4c16f4c
--- /dev/null
+++ b/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/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
new file mode 100644
index 0000000..2d4780f
--- /dev/null
+++ b/src/google/protobuf/message_unittest.cc
@@ -0,0 +1,470 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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/google/protobuf/metadata.h b/src/google/protobuf/metadata.h
new file mode 100644
index 0000000..219645d
--- /dev/null
+++ b/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 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/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
new file mode 100644
index 0000000..bc41bee
--- /dev/null
+++ b/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/google/protobuf/package_info.h b/src/google/protobuf/package_info.h
new file mode 100644
index 0000000..935e963
--- /dev/null
+++ b/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/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
new file mode 100644
index 0000000..1673e8a
--- /dev/null
+++ b/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/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
new file mode 100644
index 0000000..2838e0f
--- /dev/null
+++ b/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/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
new file mode 100755
index 0000000..671aafd
--- /dev/null
+++ b/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/google/protobuf/reflection_internal.h b/src/google/protobuf/reflection_internal.h
new file mode 100644
index 0000000..fcb4247
--- /dev/null
+++ b/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/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc
new file mode 100644
index 0000000..4629dec
--- /dev/null
+++ b/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/google/protobuf/reflection_ops.h b/src/google/protobuf/reflection_ops.h
new file mode 100644
index 0000000..4775911
--- /dev/null
+++ b/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/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
new file mode 100644
index 0000000..88d6bfb
--- /dev/null
+++ b/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/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
new file mode 100644
index 0000000..949e0a2
--- /dev/null
+++ b/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 = max(kMinRepeatedFieldAllocationSize,
+                 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/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
new file mode 100644
index 0000000..5447fa4
--- /dev/null
+++ b/src/google/protobuf/repeated_field.h
@@ -0,0 +1,2420 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+  }
+};
+
+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);
+
+// 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.
+  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. If Element has a trivial
+  // destructor (for example, if it's a primitive type, like int32), this entire
+  // loop will be removed by the optimizer.
+  if (rep_ != NULL) {
+    Element* e = &rep_->elements[0];
+    Element* limit = &rep_->elements[total_size_];
+    for (; e < limit; e++) {
+      e->Element::~Element();
+    }
+    if (rep_->arena == NULL) {
+      delete[] reinterpret_cast<char*>(rep_);
+    }
+  }
+}
+
+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 = max(google::protobuf::internal::kMinRepeatedFieldAllocationSize,
+                 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_);
+  }
+  if (old_rep) {
+    // Likewise, we need to invoke destructors on the old array. If Element has
+    // no destructor, this loop will disappear.
+    e = &old_rep->elements[0];
+    limit = &old_rep->elements[old_total_size];
+    for (; e < limit; e++) {
+      e->Element::~Element();
+    }
+    if (arena == NULL) {
+      delete[] reinterpret_cast<char*>(old_rep);
+    }
+  }
+}
+
+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_;
+};
+}  // 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);
+}
+
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_H__
diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h
new file mode 100644
index 0000000..44d14d5
--- /dev/null
+++ b/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/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
new file mode 100644
index 0000000..fcebe5c
--- /dev/null
+++ b/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/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
new file mode 100644
index 0000000..b45664b
--- /dev/null
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -0,0 +1,1528 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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());
+}
+
+}  // namespace
+
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/service.cc b/src/google/protobuf/service.cc
new file mode 100644
index 0000000..ffa919d
--- /dev/null
+++ b/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/google/protobuf/service.h b/src/google/protobuf/service.h
new file mode 100644
index 0000000..ad6f968
--- /dev/null
+++ b/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/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
new file mode 100644
index 0000000..f2eb7ae
--- /dev/null
+++ b/src/google/protobuf/source_context.pb.cc
@@ -0,0 +1,388 @@
+// 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() {
+  file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+}
+
+bool SourceContext::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const SourceContext* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void SourceContext::MergeFrom(const SourceContext& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void SourceContext::CopyFrom(const SourceContext& from) {
+  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() {
+  
+  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/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
new file mode 100644
index 0000000..02e1146
--- /dev/null
+++ b/src/google/protobuf/source_context.pb.h
@@ -0,0 +1,185 @@
+// 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() {
+  
+  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/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
new file mode 100644
index 0000000..d76252c
--- /dev/null
+++ b/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/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
new file mode 100644
index 0000000..e020597
--- /dev/null
+++ b/src/google/protobuf/struct.pb.cc
@@ -0,0 +1,1470 @@
+// 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\000BN\n\023com.google.prot"
+    "obufB\013StructProtoP\001\240\001\001\242\002\003GPB\252\002\036Google.Pr"
+    "otobuf.WellKnownTypesb\006proto3", 589);
+  ::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() {
+  fields_.Clear();
+}
+
+bool Struct::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Struct* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Struct>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Struct::MergeFrom(const Struct& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  fields_.MergeFrom(from.fields_);
+}
+
+void Struct::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Struct::CopyFrom(const Struct& from) {
+  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() {
+  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() {
+  clear_kind();
+}
+
+bool Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Value>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Value::MergeFrom(const Value& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Value::CopyFrom(const Value& from) {
+  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() {
+  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() {
+  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() {
+  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() {
+  values_.Clear();
+}
+
+bool ListValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const ListValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void ListValue::MergeFrom(const ListValue& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  values_.MergeFrom(from.values_);
+}
+
+void ListValue::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ListValue::CopyFrom(const ListValue& from) {
+  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/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
new file mode 100644
index 0000000..0527c81
--- /dev/null
+++ b/src/google/protobuf/struct.pb.h
@@ -0,0 +1,766 @@
+// 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() {
+  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() {
+  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() {
+  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/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
new file mode 100644
index 0000000..8562e2c
--- /dev/null
+++ b/src/google/protobuf/struct.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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+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 {
+  // 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/google/protobuf/stubs/atomic_sequence_num.h b/src/google/protobuf/stubs/atomic_sequence_num.h
new file mode 100644
index 0000000..bb20942
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops.h b/src/google/protobuf/stubs/atomicops.h
new file mode 100644
index 0000000..cb93227
--- /dev/null
+++ b/src/google/protobuf/stubs/atomicops.h
@@ -0,0 +1,244 @@
+// 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 (((__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/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
new file mode 100644
index 0000000..0a2d2b8
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_arm_gcc.h b/src/google/protobuf/stubs/atomicops_internals_arm_gcc.h
new file mode 100644
index 0000000..90e727b
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_arm_qnx.h b/src/google/protobuf/stubs/atomicops_internals_arm_qnx.h
new file mode 100644
index 0000000..17dfaa5
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_atomicword_compat.h b/src/google/protobuf/stubs/atomicops_internals_atomicword_compat.h
new file mode 100644
index 0000000..eb198ff
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h
new file mode 100644
index 0000000..a0116a6
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_macosx.h b/src/google/protobuf/stubs/atomicops_internals_macosx.h
new file mode 100644
index 0000000..7963324
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_mips_gcc.h b/src/google/protobuf/stubs/atomicops_internals_mips_gcc.h
new file mode 100644
index 0000000..f5837c9
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
new file mode 100644
index 0000000..3b314fd
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_power.h b/src/google/protobuf/stubs/atomicops_internals_power.h
new file mode 100644
index 0000000..b8a42f2
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_solaris.h b/src/google/protobuf/stubs/atomicops_internals_solaris.h
new file mode 100644
index 0000000..d8057ec
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_tsan.h b/src/google/protobuf/stubs/atomicops_internals_tsan.h
new file mode 100644
index 0000000..0c90354
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_x86_gcc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc
new file mode 100644
index 0000000..53c9eae
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_x86_gcc.h b/src/google/protobuf/stubs/atomicops_internals_x86_gcc.h
new file mode 100644
index 0000000..edccc59
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_x86_msvc.cc b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc
new file mode 100644
index 0000000..741b164
--- /dev/null
+++ b/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/google/protobuf/stubs/atomicops_internals_x86_msvc.h b/src/google/protobuf/stubs/atomicops_internals_x86_msvc.h
new file mode 100644
index 0000000..e53a641
--- /dev/null
+++ b/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/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc
new file mode 100644
index 0000000..f4af6a5
--- /dev/null
+++ b/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/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h
new file mode 100644
index 0000000..de8e020
--- /dev/null
+++ b/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/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc
new file mode 100644
index 0000000..06f114a
--- /dev/null
+++ b/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/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
new file mode 100644
index 0000000..87271c5
--- /dev/null
+++ b/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/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
new file mode 100644
index 0000000..be65284
--- /dev/null
+++ b/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/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
new file mode 100644
index 0000000..54dbafa
--- /dev/null
+++ b/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/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
new file mode 100644
index 0000000..9c05cac
--- /dev/null
+++ b/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/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
new file mode 100644
index 0000000..25bae9b
--- /dev/null
+++ b/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/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h
new file mode 100644
index 0000000..763a6e6
--- /dev/null
+++ b/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/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
new file mode 100755
index 0000000..5833432
--- /dev/null
+++ b/src/google/protobuf/stubs/hash.h
@@ -0,0 +1,374 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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
+#  undef GOOGLE_PROTOBUF_HAVE_HASH_MAP
+#  undef GOOGLE_PROTOBUF_HAVE_HASH_SET
+# 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) {}
+};
+
+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) {}
+};
+
+#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> {};
+
+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) {}
+};
+
+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) {}
+};
+
+#else
+
+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) {}
+};
+
+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) {}
+};
+
+#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/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
new file mode 100644
index 0000000..d80c64f
--- /dev/null
+++ b/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 <iostream>  // 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/google/protobuf/stubs/int128.h b/src/google/protobuf/stubs/int128.h
new file mode 100644
index 0000000..1499bb7
--- /dev/null
+++ b/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/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc
new file mode 100644
index 0000000..5d33292
--- /dev/null
+++ b/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/google/protobuf/stubs/logging.h b/src/google/protobuf/stubs/logging.h
new file mode 100644
index 0000000..3108db8
--- /dev/null
+++ b/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 GOOGLE_LOG_IF(INFO, 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/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h
new file mode 100644
index 0000000..0e9a9ec
--- /dev/null
+++ b/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/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h
new file mode 100644
index 0000000..4cccbbe
--- /dev/null
+++ b/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/google/protobuf/stubs/mathlimits.cc b/src/google/protobuf/stubs/mathlimits.cc
new file mode 100644
index 0000000..0373b2b
--- /dev/null
+++ b/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/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h
new file mode 100644
index 0000000..d984694
--- /dev/null
+++ b/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/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
new file mode 100644
index 0000000..3a1ef8a
--- /dev/null
+++ b/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) ? value : -value;
+  }
+
+  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/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
new file mode 100644
index 0000000..7ef1cb6
--- /dev/null
+++ b/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/google/protobuf/stubs/once.cc b/src/google/protobuf/stubs/once.cc
new file mode 100644
index 0000000..889c647
--- /dev/null
+++ b/src/google/protobuf/stubs/once.cc
@@ -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)
+//
+// 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 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/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h
new file mode 100644
index 0000000..1f082c3
--- /dev/null
+++ b/src/google/protobuf/stubs/once.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.
+
+// 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);
+
+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);
+  }
+}
+
+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/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc
new file mode 100644
index 0000000..37def58
--- /dev/null
+++ b/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/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
new file mode 100644
index 0000000..22b3572
--- /dev/null
+++ b/src/google/protobuf/stubs/platform_macros.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.
+
+#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(__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/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
new file mode 100644
index 0000000..1036dff
--- /dev/null
+++ b/src/google/protobuf/stubs/port.h
@@ -0,0 +1,384 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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
+#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)
+  #endif
+#else
+  #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 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;
+#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) x##LL
+#define GOOGLE_ULONGLONG(x) x##ULL
+#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/google/protobuf/stubs/scoped_ptr.h b/src/google/protobuf/stubs/scoped_ptr.h
new file mode 100644
index 0000000..4423c11
--- /dev/null
+++ b/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/google/protobuf/stubs/shared_ptr.h b/src/google/protobuf/stubs/shared_ptr.h
new file mode 100644
index 0000000..d250bf4
--- /dev/null
+++ b/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/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h
new file mode 100644
index 0000000..9301f54
--- /dev/null
+++ b/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/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
new file mode 100644
index 0000000..dd1bd61
--- /dev/null
+++ b/src/google/protobuf/stubs/status.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/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 Status Status::OK = Status();
+const Status Status::CANCELLED = Status(error::CANCELLED, "");
+const Status Status::UNKNOWN = Status(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::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/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h
new file mode 100644
index 0000000..614ab99
--- /dev/null
+++ b/src/google/protobuf/stubs/status.h
@@ -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.
+#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
+
+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& 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;
+
+  // 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/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h
new file mode 100644
index 0000000..743e79a
--- /dev/null
+++ b/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/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
new file mode 100644
index 0000000..c70c33c
--- /dev/null
+++ b/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/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc
new file mode 100644
index 0000000..48d1402
--- /dev/null
+++ b/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/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h
new file mode 100644
index 0000000..ad84870
--- /dev/null
+++ b/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_ : NULL) {
+}
+
+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/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
new file mode 100644
index 0000000..6e2a9e5
--- /dev/null
+++ b/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/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h
new file mode 100644
index 0000000..9e4c82a
--- /dev/null
+++ b/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/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc
new file mode 100644
index 0000000..989474b
--- /dev/null
+++ b/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/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h
new file mode 100644
index 0000000..ec3ffd5
--- /dev/null
+++ b/src/google/protobuf/stubs/stringpiece.h
@@ -0,0 +1,453 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 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/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
new file mode 100644
index 0000000..a52d81f
--- /dev/null
+++ b/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/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
new file mode 100644
index 0000000..3272d8e
--- /dev/null
+++ b/src/google/protobuf/stubs/stringprintf.cc
@@ -0,0 +1,175 @@
+// 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>
+#include <google/protobuf/testing/googletest.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/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h
new file mode 100644
index 0000000..ab1ab55
--- /dev/null
+++ b/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/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc
new file mode 100644
index 0000000..15895e5
--- /dev/null
+++ b/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/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc
new file mode 100644
index 0000000..d79a6ee
--- /dev/null
+++ b/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/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc
new file mode 100644
index 0000000..9088888
--- /dev/null
+++ b/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/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
new file mode 100644
index 0000000..7ba92e8
--- /dev/null
+++ b/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/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
new file mode 100644
index 0000000..27d4757
--- /dev/null
+++ b/src/google/protobuf/stubs/strutil.h
@@ -0,0 +1,868 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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()) {}
+
+  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);
+
+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/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
new file mode 100644
index 0000000..5d62fc4
--- /dev/null
+++ b/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/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc
new file mode 100644
index 0000000..c9d9589
--- /dev/null
+++ b/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/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h
new file mode 100644
index 0000000..7ee442a
--- /dev/null
+++ b/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/google/protobuf/stubs/template_util.h b/src/google/protobuf/stubs/template_util.h
new file mode 100644
index 0000000..feef904
--- /dev/null
+++ b/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/google/protobuf/stubs/template_util_unittest.cc b/src/google/protobuf/stubs/template_util_unittest.cc
new file mode 100644
index 0000000..b1745e2
--- /dev/null
+++ b/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/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc
new file mode 100644
index 0000000..49c0412
--- /dev/null
+++ b/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/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h
new file mode 100644
index 0000000..20a6b56
--- /dev/null
+++ b/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/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc
new file mode 100644
index 0000000..59e9d1c
--- /dev/null
+++ b/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/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
new file mode 100644
index 0000000..0d8127e
--- /dev/null
+++ b/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/google/protobuf/stubs/type_traits_unittest.cc b/src/google/protobuf/stubs/type_traits_unittest.cc
new file mode 100644
index 0000000..49c10ac
--- /dev/null
+++ b/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/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
new file mode 100644
index 0000000..07aa1d7
--- /dev/null
+++ b/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/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
new file mode 100644
index 0000000..1c13a1a
--- /dev/null
+++ b/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/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
new file mode 100644
index 0000000..388c0cb
--- /dev/null
+++ b/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/google/protobuf/test_util_lite.h b/src/google/protobuf/test_util_lite.h
new file mode 100644
index 0000000..47a2269
--- /dev/null
+++ b/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/google/protobuf/testdata/bad_utf8_string b/src/google/protobuf/testdata/bad_utf8_string
new file mode 100644
index 0000000..a1337ec
--- /dev/null
+++ b/src/google/protobuf/testdata/bad_utf8_string
@@ -0,0 +1 @@
+rÿ
\ No newline at end of file
diff --git a/src/google/protobuf/testdata/golden_message b/src/google/protobuf/testdata/golden_message
new file mode 100644
index 0000000..0b7e655
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message
Binary files differ
diff --git a/src/google/protobuf/testdata/golden_message_oneof_implemented b/src/google/protobuf/testdata/golden_message_oneof_implemented
new file mode 100644
index 0000000..b48c898
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_oneof_implemented
Binary files differ
diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3
new file mode 100644
index 0000000..bd646a0
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_message_proto3
Binary files differ
diff --git a/src/google/protobuf/testdata/golden_packed_fields_message b/src/google/protobuf/testdata/golden_packed_fields_message
new file mode 100644
index 0000000..ee28d38
--- /dev/null
+++ b/src/google/protobuf/testdata/golden_packed_fields_message
Binary files differ
diff --git a/src/google/protobuf/testdata/map_test_data.txt b/src/google/protobuf/testdata/map_test_data.txt
new file mode 100644
index 0000000..bc27232
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_data.txt b/src/google/protobuf/testdata/text_format_unittest_data.txt
new file mode 100644
index 0000000..7a874b5
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt
new file mode 100644
index 0000000..ec95e1e
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt
new file mode 100644
index 0000000..e1011eb
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt
new file mode 100644
index 0000000..95109f6
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt
new file mode 100644
index 0000000..8c8b1eb
--- /dev/null
+++ b/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/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt
new file mode 100644
index 0000000..132f744
--- /dev/null
+++ b/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/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
new file mode 100644
index 0000000..3d07b12
--- /dev/null
+++ b/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/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h
new file mode 100644
index 0000000..2f63f80
--- /dev/null
+++ b/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/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
new file mode 100644
index 0000000..2b9cdde
--- /dev/null
+++ b/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/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h
new file mode 100644
index 0000000..c0d99e6
--- /dev/null
+++ b/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/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc
new file mode 100644
index 0000000..76f8cfe
--- /dev/null
+++ b/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/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc
new file mode 100644
index 0000000..992ddc6
--- /dev/null
+++ b/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/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
new file mode 100644
index 0000000..b0a5ce6
--- /dev/null
+++ b/src/google/protobuf/text_format.cc
@@ -0,0 +1,1972 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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::PrintToString(*this, &debug_string);
+
+  return debug_string;
+}
+
+string Message::ShortDebugString() const {
+  string debug_string;
+
+  TextFormat::Printer printer;
+  printer.SetSingleLineMode(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.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, int size) {
+    int pos = 0;  // The number of bytes we've written so far.
+
+    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'.
+        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, int 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);
+      int64 size = value.size();
+      if (truncate_string_field_longer_than_ > 0) {
+        size = std::min(truncate_string_field_longer_than_,
+                        static_cast<int64>(value.size()));
+      }
+      string truncated_value(value.substr(0, size) + "...<truncated>...");
+      const string* value_to_print = &value;
+      if (size < value.size()) {
+        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/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
new file mode 100644
index 0000000..ef3d4a8
--- /dev/null
+++ b/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/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
new file mode 100644
index 0000000..8d61be1
--- /dev/null
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -0,0 +1,1482 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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/mathlimits.h>
+#include <google/protobuf/stubs/substitute.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 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/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
new file mode 100644
index 0000000..c1c4402
--- /dev/null
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -0,0 +1,434 @@
+// 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(\005BT\n\023com.google.protobufB\016"
+    "TimestampProtoP\001\240\001\001\370\001\001\242\002\003GPB\252\002\036Google.Pr"
+    "otobuf.WellKnownTypesb\006proto3", 189);
+  ::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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Timestamp*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Timestamp* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Timestamp::MergeFrom(const Timestamp& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Timestamp::CopyFrom(const Timestamp& from) {
+  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/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
new file mode 100644
index 0000000..7bf6259
--- /dev/null
+++ b/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/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
new file mode 100644
index 0000000..b51fc3f
--- /dev/null
+++ b/src/google/protobuf/timestamp.proto
@@ -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.
+
+syntax = "proto3";
+
+package google.protobuf;
+
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
+option cc_enable_arenas = true;
+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/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
new file mode 100644
index 0000000..7b47b3b
--- /dev/null
+++ b/src/google/protobuf/type.pb.cc
@@ -0,0 +1,3231 @@
+// 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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Type* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Type>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Type::MergeFrom(const Type& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Type::CopyFrom(const Type& from) {
+  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() {
+  
+  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() {
+  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() {
+  
+  ::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() {
+#define ZR_HELPER_(f) reinterpret_cast<char*>(\
+  &reinterpret_cast<Field*>(16)->f)
+
+#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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Field* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Field>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Field::MergeFrom(const Field& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Field::CopyFrom(const Field& from) {
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Enum* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Enum>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Enum::MergeFrom(const Enum& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Enum::CopyFrom(const Enum& from) {
+  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() {
+  
+  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() {
+  
+  ::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() {
+  name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());
+  number_ = 0;
+  options_.Clear();
+}
+
+bool EnumValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const EnumValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void EnumValue::MergeFrom(const EnumValue& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void EnumValue::CopyFrom(const EnumValue& from) {
+  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() {
+  
+  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() {
+  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 (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Option* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Option>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Option::MergeFrom(const Option& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Option::CopyFrom(const Option& from) {
+  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() {
+  
+  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() {
+  
+  ::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/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
new file mode 100644
index 0000000..76fe8a6
--- /dev/null
+++ b/src/google/protobuf/type.pb.h
@@ -0,0 +1,1696 @@
+// 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() {
+  
+  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() {
+  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() {
+  
+  ::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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  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() {
+  
+  ::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() {
+  
+  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() {
+  
+  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() {
+  
+  ::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/google/protobuf/type.proto b/src/google/protobuf/type.proto
new file mode 100644
index 0000000..1c9cf53
--- /dev/null
+++ b/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/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
new file mode 100644
index 0000000..85fe615
--- /dev/null
+++ b/src/google/protobuf/unittest.proto
@@ -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)
+//  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/google/protobuf/unittest_arena.proto b/src/google/protobuf/unittest_arena.proto
new file mode 100644
index 0000000..cd7e437
--- /dev/null
+++ b/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/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto
new file mode 100644
index 0000000..4cc0e36
--- /dev/null
+++ b/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/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto
new file mode 100644
index 0000000..8aa3a37
--- /dev/null
+++ b/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/google/protobuf/unittest_embed_optimize_for.proto b/src/google/protobuf/unittest_embed_optimize_for.proto
new file mode 100644
index 0000000..d8b0f9b
--- /dev/null
+++ b/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/google/protobuf/unittest_empty.proto b/src/google/protobuf/unittest_empty.proto
new file mode 100644
index 0000000..36443e7
--- /dev/null
+++ b/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/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
new file mode 100644
index 0000000..6e65dc1
--- /dev/null
+++ b/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/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto
new file mode 100644
index 0000000..8d03e38
--- /dev/null
+++ b/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/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto
new file mode 100644
index 0000000..a7afa45
--- /dev/null
+++ b/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/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto
new file mode 100644
index 0000000..59673ea
--- /dev/null
+++ b/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/google/protobuf/unittest_import_public.proto b/src/google/protobuf/unittest_import_public.proto
new file mode 100644
index 0000000..ffaf773
--- /dev/null
+++ b/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/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto
new file mode 100644
index 0000000..33549c2
--- /dev/null
+++ b/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/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto
new file mode 100644
index 0000000..d6f11e2
--- /dev/null
+++ b/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/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto
new file mode 100644
index 0000000..662c0e4
--- /dev/null
+++ b/src/google/protobuf/unittest_lite.proto
@@ -0,0 +1,385 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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;
+  }
+
+  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;
+  }
+}
+
+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;
+}
diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto
new file mode 100644
index 0000000..132d6a8
--- /dev/null
+++ b/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/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
new file mode 100644
index 0000000..49d9ada
--- /dev/null
+++ b/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/google/protobuf/unittest_mset_wire_format.proto b/src/google/protobuf/unittest_mset_wire_format.proto
new file mode 100644
index 0000000..04e4352
--- /dev/null
+++ b/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/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto
new file mode 100644
index 0000000..41518df
--- /dev/null
+++ b/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/google/protobuf/unittest_no_arena_import.proto b/src/google/protobuf/unittest_no_arena_import.proto
new file mode 100644
index 0000000..072af49
--- /dev/null
+++ b/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/google/protobuf/unittest_no_arena_lite.proto b/src/google/protobuf/unittest_no_arena_lite.proto
new file mode 100644
index 0000000..34c7b7c
--- /dev/null
+++ b/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/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto
new file mode 100644
index 0000000..994afff
--- /dev/null
+++ b/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/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto
new file mode 100644
index 0000000..8fc7713
--- /dev/null
+++ b/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/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto
new file mode 100644
index 0000000..ee9cc7b
--- /dev/null
+++ b/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/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
new file mode 100644
index 0000000..2f91332
--- /dev/null
+++ b/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/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
new file mode 100644
index 0000000..adf4296
--- /dev/null
+++ b/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/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto
new file mode 100644
index 0000000..f59d217
--- /dev/null
+++ b/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/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto
new file mode 100644
index 0000000..b835a6b
--- /dev/null
+++ b/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/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto
new file mode 100644
index 0000000..c907524
--- /dev/null
+++ b/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/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
new file mode 100644
index 0000000..d4e383d
--- /dev/null
+++ b/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/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
new file mode 100644
index 0000000..612a942
--- /dev/null
+++ b/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/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
new file mode 100644
index 0000000..5de7263
--- /dev/null
+++ b/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/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
new file mode 100644
index 0000000..9f61326
--- /dev/null
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -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.
+
+// 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:
+      COMPARE_FIELD(String);
+    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/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
new file mode 100644
index 0000000..8b83c69
--- /dev/null
+++ b/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 four modes of floating
+// point value comparison: exact, approximate using MathUtil::AlmostEqual
+// method, and arbitrarilly 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/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
new file mode 100644
index 0000000..23f7d51
--- /dev/null
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -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.
+
+// 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/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
new file mode 100644
index 0000000..c59f43aa
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -0,0 +1,418 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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::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/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
new file mode 100644
index 0000000..92f6989
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -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.
+
+#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 according to proto3 JSON
+  // spec for FieldMask (e.g., "foo,bar,baz.quz").
+  static string ToString(const FieldMask& mask);
+  static void FromString(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:
+  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/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
new file mode 100644
index 0000000..a952325
--- /dev/null
+++ b/src/google/protobuf/util/field_mask_util_test.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.
+
+#include <google/protobuf/util/field_mask_util.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 {
+namespace {
+
+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");
+  EXPECT_EQ("foo", FieldMaskUtil::ToString(mask));
+  mask.add_paths("bar");
+  EXPECT_EQ("foo,bar", FieldMaskUtil::ToString(mask));
+
+  FieldMaskUtil::FromString("", &mask);
+  EXPECT_EQ(0, mask.paths_size());
+  FieldMaskUtil::FromString("foo", &mask);
+  EXPECT_EQ(1, mask.paths_size());
+  EXPECT_EQ("foo", mask.paths(0));
+  FieldMaskUtil::FromString("foo,bar", &mask);
+  EXPECT_EQ(2, mask.paths_size());
+  EXPECT_EQ("foo", mask.paths(0));
+  EXPECT_EQ("bar", 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/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
new file mode 100644
index 0000000..0cb8f6e
--- /dev/null
+++ b/src/google/protobuf/util/internal/constants.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.
+
+#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[] = "%Y-%m-%dT%H:%M:%S";
+
+// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value.
+const int64 kMinSeconds = -315576000000;
+
+// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value.
+const int64 kMaxSeconds = 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/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
new file mode 100644
index 0000000..b557429
--- /dev/null
+++ b/src/google/protobuf/util/internal/datapiece.cc
@@ -0,0 +1,324 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 (!WebSafeBase64Unescape(str_, &decoded)) {
+      if (!Base64Unescape(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 {
+  To result;
+  if (func(str_, &result)) return result;
+  return InvalidArgument(StrCat("\"", str_.ToString(), "\""));
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
new file mode 100644
index 0000000..f22bfe7
--- /dev/null
+++ b/src/google/protobuf/util/internal/datapiece.h
@@ -0,0 +1,213 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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) {}
+  explicit DataPiece(StringPiece value)
+      : type_(TYPE_STRING),
+        str_(StringPiecePod::CreateFromStringPiece(value)) {}
+  // Constructor for bytes. The second parameter is not used.
+  explicit DataPiece(StringPiece value, bool dummy)
+      : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {}
+  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;
+
+  // Data type for this piece of data.
+  Type type_;
+
+  // 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 {
+    const char* data;
+    int size;
+
+    // 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);
+    }
+
+    string ToString() const { return string(data, size); }
+  };
+
+  // Stored piece of data.
+  union {
+    int32 i32_;
+    int64 i64_;
+    uint32 u32_;
+    uint64 u64_;
+    double double_;
+    float float_;
+    bool bool_;
+    StringPiecePod str_;
+  };
+};
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+
+}  // namespace google
+#endif  // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
new file mode 100644
index 0000000..a63e560
--- /dev/null
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc
@@ -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.
+
+#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).*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),
+      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()));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
+    StringPiece name, StringPiece value) {
+  if (current_ == NULL) {
+    ow_->RenderBytes(name, value);
+  } else {
+    RenderDataPiece(name, DataPiece(value));
+  }
+  return this;
+}
+
+DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
+    StringPiece name) {
+  if (current_ == NULL) {
+    ow_->RenderNull(name);
+  } else {
+    RenderDataPiece(name, DataPiece::NullData());
+  }
+  return this;
+}
+
+DefaultValueObjectWriter::Node::Node(const string& name,
+                                     const google::protobuf::Type* type,
+                                     NodeKind kind, const DataPiece& data,
+                                     bool is_placeholder)
+    : name_(name),
+      type_(type),
+      kind_(kind),
+      is_any_(false),
+      data_(data),
+      is_placeholder_(is_placeholder) {}
+
+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);
+    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));
+    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());
+
+  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())
+             : 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());
+    }
+    case google::protobuf::Field_Kind_TYPE_BYTES: {
+      return DataPiece(field.default_value(), false);
+    }
+    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) {
+    root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(),
+                         false));
+    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 = 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) {
+    root_.reset(
+        new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false));
+    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 = 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 = node.get();
+    current_->AddChild(node.release());
+  } else {
+    child->set_data(data);
+  }
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
new file mode 100644
index 0000000..695b9dd
--- /dev/null
+++ b/src/google/protobuf/util/internal/default_value_objectwriter.h
@@ -0,0 +1,234 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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/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:
+  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);
+
+ 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);
+    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 google::protobuf::Type* type() { return type_; }
+
+    void set_type(const google::protobuf::Type* type) { type_ = type; }
+
+    NodeKind kind() { return kind_; }
+
+    int number_of_children() { return children_.size(); }
+
+    void set_data(const DataPiece& data) { data_ = data; }
+
+    bool is_any() { 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_;
+  };
+
+  // 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_;
+
+  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/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
new file mode 100644
index 0000000..8254c0f
--- /dev/null
+++ b/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/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/util/internal/error_listener.cc
new file mode 100644
index 0000000..538307b
--- /dev/null
+++ b/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/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
new file mode 100644
index 0000000..3f06393
--- /dev/null
+++ b/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/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h
new file mode 100644
index 0000000..ae98ddd
--- /dev/null
+++ b/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/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
new file mode 100644
index 0000000..f0e8fc8
--- /dev/null
+++ b/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/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h
new file mode 100644
index 0000000..59f36f7
--- /dev/null
+++ b/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/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
new file mode 100644
index 0000000..24bd554
--- /dev/null
+++ b/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/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
new file mode 100644
index 0000000..e3e329f
--- /dev/null
+++ b/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/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
new file mode 100644
index 0000000..94d2ab7
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter.cc
@@ -0,0 +1,181 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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;
+  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/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
new file mode 100644
index 0000000..761a0a1
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter.h
@@ -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.
+
+#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()) {
+  }
+  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);
+
+ 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_;
+
+  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/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
new file mode 100644
index 0000000..9d82016
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_objectwriter_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/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_;
+  ObjectWriter* 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()));
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
new file mode 100644
index 0000000..df91675
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_stream_parser.cc
@@ -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.
+
+#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/stubs/strutil.h>
+#include <google/protobuf/util/internal/object_writer.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 a unicode escape sequence (/uXXXX)
+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]);
+  }
+  char buf[UTFmax];
+  int len = EncodeAsUTF8Char(code, buf);
+  // Advance past the unicode 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 == '-') 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) {
+    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;
+  }
+
+  // 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 = max(p_start - kContextLength, json_start);
+  const char* end = 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(
+      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/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
new file mode 100644
index 0000000..0278c28
--- /dev/null
+++ b/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/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
new file mode 100644
index 0000000..3414826
--- /dev/null
+++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc
@@ -0,0 +1,716 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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) {
+    util::Status result = RunTest(json, split);
+    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);
+  }
+}
+
+// - 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.");
+}
+
+#ifndef _MSC_VER
+// - unicode handling in strings
+TEST_F(JsonStreamParserTest, UnicodeEscaping) {
+  StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
+  for (int i = 0; i <= str.length(); ++i) {
+    // TODO(xiaofeng): Figure out what default encoding to use for JSON strings.
+    // In protobuf we use UTF-8 for strings, but for JSON we probably should
+    // allow different encodings?
+    ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList();
+    DoTest(str, i);
+  }
+}
+#endif
+
+// - 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 unicode sequence.
+TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
+  StringPiece str = "\"\\u12";
+  for (int i = 0; i <= str.length(); ++i) {
+    DoErrorTest(str, i, "Illegal hex string.");
+  }
+}
+
+TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
+  StringPiece str = "\"\\u12$4hello";
+  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/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h
new file mode 100644
index 0000000..0864b05
--- /dev/null
+++ b/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/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h
new file mode 100644
index 0000000..591c35d
--- /dev/null
+++ b/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/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h
new file mode 100644
index 0000000..8586cec
--- /dev/null
+++ b/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/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
new file mode 100644
index 0000000..2c31cfb
--- /dev/null
+++ b/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/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc
new file mode 100644
index 0000000..57cc08a
--- /dev/null
+++ b/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/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
new file mode 100644
index 0000000..e695f45
--- /dev/null
+++ b/src/google/protobuf/util/internal/object_writer.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_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);
+
+ protected:
+  ObjectWriter() {}
+
+ private:
+  // 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/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
new file mode 100644
index 0000000..47e0009
--- /dev/null
+++ b/src/google/protobuf/util/internal/proto_writer.cc
@@ -0,0 +1,744 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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;
+  }
+
+    WriteTag(*field);
+  element_.reset(new ProtoElement(element_.release(), field, *type, false));
+  return this;
+}
+
+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;
+  }
+
+  element_.reset(new ProtoElement(element_.release(), field, *type, true));
+  return this;
+}
+
+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;
+  }
+
+  // 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;
+}
+
+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;
+}
+
+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/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
new file mode 100644
index 0000000..e631e56
--- /dev/null
+++ b/src/google/protobuf/util/internal/proto_writer.h
@@ -0,0 +1,315 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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));
+  }
+  virtual ProtoWriter* RenderBytes(StringPiece name, StringPiece value) {
+    return RenderDataPiece(name, DataPiece(value, false));
+  }
+  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() const { 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);
+
+ 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/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
new file mode 100644
index 0000000..034d616
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource.cc
@@ -0,0 +1,1045 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 {
+// 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);
+}  // 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) {
+  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) {
+  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()) {
+          return Status(util::error::INTERNAL, "Map key must be non-empty");
+        }
+        RETURN_IF_ERROR(RenderField(field, map_key, ow));
+      }
+    }
+    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 > kMaxSeconds || seconds < kMinSeconds) {
+    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 > kMaxSeconds || seconds < kMinSeconds) {
+    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(WriteMessage(*type, field_name, 0, true, ow));
+    }
+    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) {
+          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);
+}
+
+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/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
new file mode 100644
index 0000000..78defa1
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource.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.
+
+#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;
+
+ 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;
+
+  // 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_;
+
+
+  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/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
new file mode 100644
index 0000000..561f676
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
@@ -0,0 +1,830 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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 <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::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::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_) {
+    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)));
+    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;
+  }
+
+  testing::TypeInfoTestHelper helper_;
+
+  ::testing::NiceMock<MockObjectWriter> mock_;
+  ExpectingObjectWriter ow_;
+};
+
+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());
+}
+
+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());
+}
+
+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());
+}
+
+}  // namespace converter
+}  // namespace util
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
new file mode 100644
index 0000000..786bf0b
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.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.
+
+#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)
+    : ProtoWriter(type_resolver, type, output, listener),
+      master_type_(type),
+      current_(NULL) {}
+
+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) {}
+
+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),
+      has_injected_value_message_(false) {}
+
+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 (!has_injected_value_message_ || depth_ != 1 || name != "value") {
+    // We don't propagate to ow_ StartObject("value") calls for nested Anys or
+    // Struct at depth 1 as they are nested one level deep with an injected
+    // "value" field.
+    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_.  If we are in a
+  // nested Any or Struct type, ignore the second to last EndObject call (depth_
+  // == -1)
+  if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) {
+    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 {
+    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 {
+    // Check to see if the data needs to be rendered with well-known-type
+    // renderer.
+    const TypeRenderer* type_renderer =
+        FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name()));
+    if (type_renderer) {
+      Status status = (*type_renderer)(ow_.get(), value);
+      if (!status.ok()) ow_->InvalidValue("Any", status.error_message());
+    } 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();
+
+  // If this is the case of an Any in an Any or Struct in an Any, we need to
+  // expect a StartObject call with "value" while we're at depth_ 0, which we
+  // should ignore (not propagate to our nested object writer). We also need to
+  // ignore the second-to-last EndObject call, and not propagate that either.
+  if (type->name() == kAnyType || type->name() == kStructType) {
+    has_injected_value_message_ = true;
+  }
+
+  // Create our object writer and initialize it with the first StartObject
+  // call.
+  ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
+                                        parent_->listener()));
+  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));
+    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));
+    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:
+    case DataPiece::TYPE_UINT64:
+    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)));
+  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 > kMaxSeconds || seconds < kMinSeconds ||
+      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));
+    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) {
+      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/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
new file mode 100644
index 0000000..08ac6e3
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter.h
@@ -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.
+
+#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:
+// Constructor. Does not take ownership of any parameter passed in.
+  ProtoStreamObjectWriter(TypeResolver* type_resolver,
+                          const google::protobuf::Type& type,
+                          strings::ByteSink* output, ErrorListener* listener);
+  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 message type contained in Any has a special "value" message
+    // injected. This is true for well-known message types like Any or Struct.
+    bool has_injected_value_message_;
+  };
+
+  // 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_;
+
+  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/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
new file mode 100644
index 0000000..5f9ffb9
--- /dev/null
+++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
@@ -0,0 +1,1895 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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
+
+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_));
+  }
+
+  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_;
+};
+
+MATCHER_P(HasObjectLocation, expected,
+          "Verifies the expected object location") {
+  string actual;
+#if __cplusplus >= 201103L
+  actual = std::get<0>(arg).ToString();
+#else
+  actual = std::tr1::get<0>(arg).ToString();
+#endif
+  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);
+
+  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+                                   output_.get(), &listener_));
+
+  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");
+
+  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+                                   output_.get(), &listener_));
+
+  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");
+
+  ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()),
+                                   output_.get(), &listener_));
+
+  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, 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: "
+                               "-8032-10-18T00:00:00.000Z")));
+
+  ow_->StartObject("")
+      ->RenderString("ts", "-8032-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, 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() {
+    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();
+}
+
+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());
+    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);
+}
+
+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/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h
new file mode 100644
index 0000000..3f065d6
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto
new file mode 100644
index 0000000..18c59cb
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto
new file mode 100644
index 0000000..82b8176
--- /dev/null
+++ b/src/google/protobuf/util/internal/testdata/books.proto
@@ -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.
+
+// 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;
+
+  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.
+}
diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto
new file mode 100644
index 0000000..cccc741
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/default_value_test.proto b/src/google/protobuf/util/internal/testdata/default_value_test.proto
new file mode 100644
index 0000000..9328834
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/field_mask.proto b/src/google/protobuf/util/internal/testdata/field_mask.proto
new file mode 100644
index 0000000..e8b2bc5
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto
new file mode 100644
index 0000000..6475ecd
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/oneofs.proto b/src/google/protobuf/util/internal/testdata/oneofs.proto
new file mode 100644
index 0000000..5bc9fa0
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/struct.proto b/src/google/protobuf/util/internal/testdata/struct.proto
new file mode 100644
index 0000000..c15aba0
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/timestamp_duration.proto b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
new file mode 100644
index 0000000..56351f1
--- /dev/null
+++ b/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/google/protobuf/util/internal/testdata/wrappers.proto b/src/google/protobuf/util/internal/testdata/wrappers.proto
new file mode 100644
index 0000000..eabc99f
--- /dev/null
+++ b/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/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
new file mode 100644
index 0000000..00a8ee7
--- /dev/null
+++ b/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/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
new file mode 100644
index 0000000..d813317
--- /dev/null
+++ b/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/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
new file mode 100644
index 0000000..1b9c515
--- /dev/null
+++ b/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 google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
+  switch (type_) {
+    case USE_TYPE_RESOLVER: {
+      return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
+                                         listener);
+    }
+  }
+  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/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
new file mode 100644
index 0000000..6916a73
--- /dev/null
+++ b/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/type_info.h>
+#include <google/protobuf/util/internal/default_value_objectwriter.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);
+
+  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/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
new file mode 100644
index 0000000..1ddf248
--- /dev/null
+++ b/src/google/protobuf/util/internal/utility.cc
@@ -0,0 +1,356 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (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;
+      } 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;
+      }
+    }
+    result.push_back(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/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
new file mode 100644
index 0000000..33df8ed
--- /dev/null
+++ b/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/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
new file mode 100644
index 0000000..a1e24c1
--- /dev/null
+++ b/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/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
new file mode 100644
index 0000000..c3b8d50
--- /dev/null
+++ b/src/google/protobuf/util/json_util.cc
@@ -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.
+
+#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);
+}
+
+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);
+  converter::NoopErrorListener 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 util::Status::OK;
+}
+
+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/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
new file mode 100644
index 0000000..1718bfb
--- /dev/null
+++ b/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/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
new file mode 100644
index 0000000..da68495
--- /dev/null
+++ b/src/google/protobuf/util/json_util_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/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;
+    GOOGLE_CHECK_OK(JsonToBinaryString(
+        resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary));
+    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));
+}
+
+// TODO(skarvaje): Uncomment after cl/96232915 is submitted.
+// 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\":\"\","
+      // // TODO(xiaofeng): The default enum value should be FOO. I believe
+      // // this is a bug in DefaultValueObjectWriter.
+      // "\"enumValue\":null"
+      // "}",
+      // 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());
+}
+
+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/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
new file mode 100644
index 0000000..0f879dc
--- /dev/null
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -0,0 +1,1686 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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.";
+    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_LOG(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_LOG(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/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
new file mode 100644
index 0000000..3ea74e6
--- /dev/null
+++ b/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/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
new file mode 100755
index 0000000..a867c88
--- /dev/null
+++ b/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/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto
new file mode 100644
index 0000000..698775f
--- /dev/null
+++ b/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/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
new file mode 100644
index 0000000..c782d69
--- /dev/null
+++ b/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/google/protobuf/util/time_util.h b/src/google/protobuf/util/time_util.h
new file mode 100644
index 0000000..1bac089
--- /dev/null
+++ b/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/google/protobuf/util/time_util_test.cc b/src/google/protobuf/util/time_util_test.cc
new file mode 100644
index 0000000..285740a
--- /dev/null
+++ b/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/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h
new file mode 100644
index 0000000..77d4416
--- /dev/null
+++ b/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/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
new file mode 100644
index 0000000..9639390
--- /dev/null
+++ b/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/google/protobuf/util/type_resolver_util.h b/src/google/protobuf/util/type_resolver_util.h
new file mode 100644
index 0000000..c0ef3c1
--- /dev/null
+++ b/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/google/protobuf/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc
new file mode 100644
index 0000000..8a0bf65
--- /dev/null
+++ b/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/google/protobuf/well_known_types_unittest.cc b/src/google/protobuf/well_known_types_unittest.cc
new file mode 100644
index 0000000..c9a9aa1
--- /dev/null
+++ b/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/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
new file mode 100644
index 0000000..5ee4e25
--- /dev/null
+++ b/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/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
new file mode 100644
index 0000000..941be75
--- /dev/null
+++ b/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/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
new file mode 100644
index 0000000..7f1093c
--- /dev/null
+++ b/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(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(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(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(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/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h
new file mode 100644
index 0000000..55fc7ec
--- /dev/null
+++ b/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/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h
new file mode 100644
index 0000000..79493ca
--- /dev/null
+++ b/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 = 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 =
+        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/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
new file mode 100644
index 0000000..15c3755
--- /dev/null
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -0,0 +1,1288 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING 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/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/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
new file mode 100644
index 0000000..212dd21
--- /dev/null
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -0,0 +1,2695 @@
+// 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(\014BS\n\023com"
+    ".google.protobufB\rWrappersProtoP\001\240\001\001\370\001\001\242"
+    "\002\003GPB\252\002\036Google.Protobuf.WellKnownTypesb\006"
+    "proto3", 406);
+  ::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() {
+  value_ = 0;
+}
+
+bool DoubleValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const DoubleValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void DoubleValue::MergeFrom(const DoubleValue& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void DoubleValue::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void DoubleValue::CopyFrom(const DoubleValue& from) {
+  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() {
+  value_ = 0;
+}
+
+bool FloatValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const FloatValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void FloatValue::MergeFrom(const FloatValue& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void FloatValue::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void FloatValue::CopyFrom(const FloatValue& from) {
+  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() {
+  value_ = GOOGLE_LONGLONG(0);
+}
+
+bool Int64Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Int64Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Int64Value::MergeFrom(const Int64Value& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void Int64Value::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Int64Value::CopyFrom(const Int64Value& from) {
+  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() {
+  value_ = GOOGLE_ULONGLONG(0);
+}
+
+bool UInt64Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UInt64Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void UInt64Value::MergeFrom(const UInt64Value& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void UInt64Value::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UInt64Value::CopyFrom(const UInt64Value& from) {
+  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() {
+  value_ = 0;
+}
+
+bool Int32Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const Int32Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Int32Value::MergeFrom(const Int32Value& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void Int32Value::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Int32Value::CopyFrom(const Int32Value& from) {
+  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() {
+  value_ = 0u;
+}
+
+bool UInt32Value::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const UInt32Value* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void UInt32Value::MergeFrom(const UInt32Value& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void UInt32Value::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UInt32Value::CopyFrom(const UInt32Value& from) {
+  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() {
+  value_ = false;
+}
+
+bool BoolValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const BoolValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void BoolValue::MergeFrom(const BoolValue& from) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  if (from.value() != 0) {
+    set_value(from.value());
+  }
+}
+
+void BoolValue::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void BoolValue::CopyFrom(const BoolValue& from) {
+  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() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+
+bool StringValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const StringValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void StringValue::MergeFrom(const StringValue& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void StringValue::CopyFrom(const StringValue& from) {
+  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() {
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* StringValue::unsafe_arena_release_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_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() {
+  value_.ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+
+bool BytesValue::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(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 {
+  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) {
+  if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);
+  const BytesValue* source = 
+      ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>(
+          &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void BytesValue::MergeFrom(const BytesValue& from) {
+  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) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void BytesValue::CopyFrom(const BytesValue& from) {
+  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() {
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+ ::std::string* BytesValue::unsafe_arena_release_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_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/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
new file mode 100644
index 0000000..7dca938
--- /dev/null
+++ b/src/google/protobuf/wrappers.pb.h
@@ -0,0 +1,1176 @@
+// 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() {
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* StringValue::unsafe_arena_release_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_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() {
+  
+  return value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual());
+}
+inline ::std::string* BytesValue::unsafe_arena_release_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_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/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
new file mode 100644
index 0000000..040d8a2
--- /dev/null
+++ b/src/google/protobuf/wrappers.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.
+
+// 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 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/solaris/libstdc++.la b/src/solaris/libstdc++.la
new file mode 100644
index 0000000..3edf425
--- /dev/null
+++ b/src/solaris/libstdc++.la
@@ -0,0 +1,51 @@
+# libstdc++.la - a libtool library file
+# Generated by ltmain.sh - GNU libtool 1.4a-GCC3.0 (1.641.2.256 2001/05/28 20:09:07 with GCC-local changes)
+#
+# Please DO NOT delete this file!
+# It is necessary for linking the library.
+
+# ---
+# NOTE: This file lives in /usr/sfw/lib on Solaris 10.  Unfortunately,
+# due to an apparent bug in the Solaris 10 6/06 release,
+# /usr/sfw/lib/libstdc++.la is empty.  Below is the correct content,
+# according to
+#    http://forum.java.sun.com/thread.jspa?threadID=5073150
+# By passing LDFLAGS='-Lsrc/solaris' to configure, make will pick up
+# this copy of the file rather than the empty copy in /usr/sfw/lib.
+#
+# Also see
+#   http://www.technicalarticles.org/index.php/Compiling_MySQL_5.0_on_Solaris_10
+#
+# Note: this is for 32-bit systems.  If you have a 64-bit system,
+# uncomment the appropriate dependency_libs line below.
+# ----
+
+# The name that we can dlopen(3).
+dlname='libstdc++.so.6'
+
+# Names of this library.
+library_names='libstdc++.so.6.0.3 libstdc++.so.6 libstdc++.so'
+
+# The name of the static archive.
+old_library='libstdc++.a'
+
+# Libraries that this one depends upon.
+# 32-bit version:
+dependency_libs='-lc -lm -L/usr/sfw/lib -lgcc_s'
+# 64-bit version:
+#dependency_libs='-L/lib/64 -lc -lm -L/usr/sfw/lib/64 -lgcc_s'
+
+# Version information for libstdc++.
+current=6
+age=0
+revision=3
+
+# Is this an already installed library?
+installed=yes
+
+# Files to dlopen/dlpreopen
+dlopen=''
+dlpreopen=''
+
+# Directory that this library needs to be installed in:
+libdir='/usr/sfw/lib'