aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rw-r--r--CHANGES.txt104
-rw-r--r--Makefile.am14
-rwxr-xr-xautogen.sh12
-rw-r--r--configure.ac6
-rw-r--r--java/pom.xml4
-rw-r--r--java/src/main/java/com/google/protobuf/MapFieldLite.java2
-rw-r--r--java/src/test/java/com/google/protobuf/MapTest.java7
-rw-r--r--java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java5
-rwxr-xr-xpost_process_dist.sh24
-rwxr-xr-xpython/setup.py2
-rw-r--r--ruby/README.md34
-rw-r--r--ruby/Rakefile37
-rw-r--r--ruby/ext/protobuf_c/defs.c1286
-rw-r--r--ruby/ext/protobuf_c/encode_decode.c755
-rw-r--r--ruby/ext/protobuf_c/extconf.rb23
-rw-r--r--ruby/ext/protobuf_c/message.c463
-rw-r--r--ruby/ext/protobuf_c/protobuf.c102
-rw-r--r--ruby/ext/protobuf_c/protobuf.h404
-rw-r--r--ruby/ext/protobuf_c/repeated_field.c597
-rw-r--r--ruby/ext/protobuf_c/storage.c577
-rw-r--r--ruby/lib/protobuf.rb31
-rw-r--r--ruby/tests/basic.rb633
-rw-r--r--ruby/tests/stress.rb38
-rw-r--r--src/Makefile.am11
-rw-r--r--src/google/protobuf/arena.cc21
-rw-r--r--src/google/protobuf/arena.h11
-rw-r--r--src/google/protobuf/arena_unittest.cc12
-rwxr-xr-xsrc/google/protobuf/arenastring.h3
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_message.cc2
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc3
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc2
-rw-r--r--src/google/protobuf/compiler/main.cc7
-rw-r--r--src/google/protobuf/compiler/parser_unittest.cc58
-rw-r--r--src/google/protobuf/compiler/plugin.pb.h4
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.cc313
-rw-r--r--src/google/protobuf/compiler/ruby/ruby_generator.h57
-rw-r--r--src/google/protobuf/descriptor.cc5
-rw-r--r--src/google/protobuf/descriptor.pb.h4
-rw-r--r--src/google/protobuf/descriptor_unittest.cc4
-rw-r--r--src/google/protobuf/map.h6
-rw-r--r--src/google/protobuf/map_entry.h13
-rw-r--r--src/google/protobuf/map_field.cc27
-rw-r--r--src/google/protobuf/map_field.h2
-rw-r--r--src/google/protobuf/map_field_test.cc35
-rw-r--r--src/google/protobuf/map_test.cc2
-rw-r--r--src/google/protobuf/map_test_util.cc34
-rw-r--r--src/google/protobuf/message.h1
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc2
-rw-r--r--src/google/protobuf/repeated_field.h13
-rw-r--r--src/google/protobuf/repeated_field_reflection.h4
-rw-r--r--src/google/protobuf/repeated_field_reflection_unittest.cc5
-rw-r--r--src/google/protobuf/repeated_field_unittest.cc4
-rw-r--r--src/google/protobuf/stubs/common.h16
-rw-r--r--src/google/protobuf/stubs/common_unittest.cc14
-rw-r--r--src/google/protobuf/stubs/fastmem.h1
-rw-r--r--src/google/protobuf/stubs/type_traits.h11
-rw-r--r--src/google/protobuf/stubs/type_traits_unittest.cc2
-rw-r--r--src/google/protobuf/unknown_field_set_unittest.cc2
m---------upb0
-rwxr-xr-xvsprojects/extract_includes.bat78
-rw-r--r--vsprojects/libprotobuf-lite.vcproj34
-rw-r--r--vsprojects/libprotobuf.vcproj90
-rw-r--r--vsprojects/libprotoc.vcproj88
-rw-r--r--vsprojects/lite-test.vcproj4
-rw-r--r--vsprojects/protoc.vcproj4
-rw-r--r--vsprojects/readme.txt7
-rwxr-xr-xvsprojects/test_plugin.vcproj4
-rw-r--r--vsprojects/tests.vcproj540
71 files changed, 6403 insertions, 323 deletions
diff --git a/.gitignore b/.gitignore
index dd69a344..3938196c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,3 +60,4 @@ src/protobuf*-test
src/test_plugin
src/testzip.*
src/zcg*zip
+ar-lib
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..5351ea07
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "upb"]
+ path = upb
+ url = https://github.com/haberman/upb
diff --git a/CHANGES.txt b/CHANGES.txt
index 0d0ac814..0d4ce0ec 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,107 @@
+2014-12-01 version 3.0.0-alpha-1 (C++/Java):
+
+ General
+ * Introduced Protocol Buffers language version 3 (aka proto3).
+
+ When protobuf was initially opensourced it implemented Protocol Buffers
+ language version 2 (aka proto2), which is why the version number
+ started from v2.0.0. From v3.0.0, a new language version (proto3) is
+ introduced while the old version (proto2) will continue to be supported.
+
+ The main intent of introducing proto3 is to clean up protobuf before
+ pushing the language as the foundation of Google's new API platform.
+ In proto3, the language is simplified, both for ease of use and to
+ make it available in a wider range of programming languages. At the
+ same time a few features are added to better support common idioms
+ found in APIs.
+
+ The following are the main new features in language version 3:
+
+ 1. Removal of field presence logic for primitive value fields, removal
+ of required fields, and removal of default values. This makes proto3
+ significantly easier to implement with open struct representations,
+ as in languages like Android Java, Objective C, or Go.
+ 2. Removal of unknown fields.
+ 3. Removal of extensions, which are instead replaced by a new standard
+ type called Any.
+ 4. Fix semantics for unknown enum values.
+ 5. Addition of maps.
+ 6. Addition of a small set of standard types for representation of time,
+ dynamic data, etc.
+ 7. A well-defined encoding in JSON as an alternative to binary proto
+ encoding.
+
+ This release (v3.0.0-alpha-1) includes partial proto3 support for C++ and
+ Java. Items 6 (well-known types) and 7 (JSON format) in the above feature
+ list are not impelmented.
+
+ A new notion "syntax" is introduced to specify whether a .proto file
+ uses proto2 or proto3:
+
+ // foo.proto
+ syntax = "proto3";
+ message Bar {...}
+
+ If omitted, the protocol compiler will generate a warning and "proto2" will
+ be used as the default. This warning will be turned into an error in a
+ future release.
+
+ We recommend that new Protocol Buffers users use proto3. However, we do not
+ generally recommend that existing users migrate from proto2 from proto3 due
+ to API incompatibility, and we will continue to support proto2 for a long
+ time.
+
+ * Added support for map fields (implemented in C++/Java for both proto2 and
+ proto3).
+
+ Map fields can be declared using the following syntax:
+
+ message Foo {
+ map<string, string> values = 1;
+ }
+
+ Data of a map field will be stored in memory as an unordered map and it
+ can be accessed through generated accessors.
+
+ C++
+ * Added arena allocation support (for both proto2 and proto3).
+
+ Profiling shows memory allocation and deallocation constitutes a significant
+ fraction of CPU-time spent in protobuf code and arena allocation is a
+ technique introduced to reduce this cost. With arena allocation, new
+ objects will be allocated from a large piece of preallocated memory and
+ deallocation of these objects is almost free. Early adoption shows 20% to
+ 50% improvement in some Google binaries.
+
+ To enable arena support, add the following option to your .proto file:
+
+ option cc_enable_arenas = true;
+
+ Protocol compiler will generate additional code to make the generated
+ message classes work with arenas. This does not change the existing API
+ of protobuf messages and does not affect wire format. Your existing code
+ should continue to work after adding this option. In the future we will
+ make this option enabled by default.
+
+ To actually take advantage of arena allocation, you need to use the arena
+ APIs when creating messages. A quick example of using the arena API:
+
+ {
+ google::protobuf::Arena arena;
+ // Allocate a protobuf message in the arena.
+ MyMessage* message = Arena::CreateMessage<MyMessage>(&arena);
+ // All submessages will be allocated in the same arena.
+ if (!message->ParseFromString(data)) {
+ // Deal with malformed input data.
+ }
+ // Must not delete the message here. It will be deleted automatically
+ // when the arena is destroyed.
+ }
+
+ Currently arena does not work with map fields. Enabling arena in a .proto
+ file containing map fields will result in compile errors in the generated
+ code. This will be addressed in a future release.
+
2014-10-20 version 2.6.1:
C++
diff --git a/Makefile.am b/Makefile.am
index 6bda5157..dadccf25 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -135,6 +135,7 @@ java_EXTRA_DIST= \
java/src/test/java/com/google/protobuf/field_presence_test.proto \
java/src/test/java/com/google/protobuf/lazy_fields_lite.proto \
java/src/test/java/com/google/protobuf/lite_equals_and_hash.proto \
+ java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto \
java/src/test/java/com/google/protobuf/map_for_proto2_test.proto \
java/src/test/java/com/google/protobuf/map_test.proto \
java/src/test/java/com/google/protobuf/multiple_files_test.proto \
@@ -238,7 +239,18 @@ python_EXTRA_DIST= \
python/stubout.py \
python/README.txt
-all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST)
+ruby_EXTRA_DIST= \
+ ruby/ext/defs.c \
+ ruby/ext/encode_decode.c \
+ ruby/ext/extconf.rb \
+ ruby/ext/message.c \
+ ruby/ext/protobuf.c \
+ ruby/ext/protobuf.h \
+ ruby/ext/repeated_field.c \
+ ruby/ext/storage.c \
+ ruby/ext/test.rb
+
+all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
autogen.sh \
diff --git a/autogen.sh b/autogen.sh
index c3e026d2..c18474bf 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -18,9 +18,11 @@ fi
# Check that gtest is present. Usually it is already there since the
# directory is set up as an SVN external.
if test ! -e gtest; then
- echo "Google Test not present. Fetching gtest-1.5.0 from the web..."
- curl http://googletest.googlecode.com/files/gtest-1.5.0.tar.bz2 | tar jx
- mv gtest-1.5.0 gtest
+ echo "Google Test not present. Fetching gtest-1.7.0 from the web..."
+ curl -O https://googletest.googlecode.com/files/gtest-1.7.0.zip
+ unzip -q gtest-1.7.0.zip
+ rm gtest-1.7.0.zip
+ mv gtest-1.7.0 gtest
fi
set -ex
@@ -37,5 +39,9 @@ sed -i -e 's/RuntimeLibrary="5"/RuntimeLibrary="3"/g;
# TODO(kenton): Remove the ",no-obsolete" part and fix the resulting warnings.
autoreconf -f -i -Wall,no-obsolete
+# pull down git submodules.
+git submodule init
+git submodule update
+
rm -rf autom4te.cache config.h.in~
exit 0
diff --git a/configure.ac b/configure.ac
index 034d0cdb..d1fde9d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -12,7 +12,7 @@ AC_PREREQ(2.59)
# In the SVN trunk, the version should always be the next anticipated release
# version with the "-pre" suffix. (We used to use "-SNAPSHOT" but this pushed
# the size of one file name in the dist tarfile over the 99-char limit.)
-AC_INIT([Protocol Buffers],[2.6.2-pre],[protobuf@googlegroups.com],[protobuf])
+AC_INIT([Protocol Buffers],[3.0.0-pre],[protobuf@googlegroups.com],[protobuf])
AM_MAINTAINER_MODE([enable])
@@ -22,8 +22,8 @@ AC_CONFIG_MACRO_DIR([m4])
AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
case "$DIST_LANG" in
- "") DIST_LANG=cpp ;;
- all | cpp | java | python | javanano) ;;
+ "") DIST_LANG=all ;;
+ all | cpp | java | python | javanano | ruby) ;;
*) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
esac
AC_SUBST(DIST_LANG)
diff --git a/java/pom.xml b/java/pom.xml
index 4ec6d776..bbadc656 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -10,7 +10,7 @@
</parent>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
- <version>2.6.2-pre</version>
+ <version>3.0.0-pre</version>
<packaging>bundle</packaging>
<name>Protocol Buffer Java API</name>
<description>
@@ -152,7 +152,7 @@
<instructions>
<Bundle-DocURL>https://developers.google.com/protocol-buffers/</Bundle-DocURL>
<Bundle-SymbolicName>com.google.protobuf</Bundle-SymbolicName>
- <Export-Package>com.google.protobuf;version=2.6.2-pre</Export-Package>
+ <Export-Package>com.google.protobuf;version=3.0.0-pre</Export-Package>
</instructions>
</configuration>
</plugin>
diff --git a/java/src/main/java/com/google/protobuf/MapFieldLite.java b/java/src/main/java/com/google/protobuf/MapFieldLite.java
index eea36d9e..7f94c690 100644
--- a/java/src/main/java/com/google/protobuf/MapFieldLite.java
+++ b/java/src/main/java/com/google/protobuf/MapFieldLite.java
@@ -97,7 +97,7 @@ public class MapFieldLite<K, V> {
if (a == b) {
return true;
}
- if (a.size() != a.size()) {
+ if (a.size() != b.size()) {
return false;
}
for (Map.Entry<K, V> entry : a.entrySet()) {
diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java
index 542a20e7..9a25e302 100644
--- a/java/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/src/test/java/com/google/protobuf/MapTest.java
@@ -260,6 +260,13 @@ public class MapTest extends TestCase {
assertFalse(m1.equals(m2));
// Don't check m1.hashCode() != m2.hashCode() because it's not guaranteed
// to be different.
+
+ // Regression test for b/18549190: if a map is a subset of the other map,
+ // equals() should return false.
+ b2.getMutableInt32ToInt32Field().remove(1);
+ m2 = b2.build();
+ assertFalse(m1.equals(m2));
+ assertFalse(m2.equals(m1));
}
diff --git a/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java b/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
index 6372b7a7..cec3da1e 100644
--- a/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
+++ b/java/src/test/java/com/google/protobuf/UnknownFieldSetLiteTest.java
@@ -38,7 +38,6 @@ import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
/**
* Tests for {@link UnknownFieldSetLite}.
@@ -228,9 +227,9 @@ public class UnknownFieldSetLiteTest extends TestCase {
assertEquals(foo, copyOfCopy);
}
- public void testMalformedBytes() {
+ public void testMalformedBytes() throws Exception {
try {
- Foo.parseFrom("this is a malformed protocol buffer".getBytes(StandardCharsets.UTF_8));
+ Foo.parseFrom("this is a malformed protocol buffer".getBytes("UTF-8"));
fail();
} catch (InvalidProtocolBufferException e) {
// Expected.
diff --git a/post_process_dist.sh b/post_process_dist.sh
index 7b2e599d..733fa088 100755
--- a/post_process_dist.sh
+++ b/post_process_dist.sh
@@ -16,7 +16,7 @@
# 5) Cleans up after itself.
if [ "$1" == "" ]; then
- echo "USAGE: $1 DISTFILE" >&2
+ echo "USAGE: $0 DISTFILE" >&2
exit 1
fi
@@ -27,7 +27,9 @@ fi
set -ex
+LANGUAGES="cpp java python"
BASENAME=`basename $1 .tar.gz`
+VERSION=${BASENAME:9}
# Create a directory called "dist", copy the tarball there and unpack it.
mkdir dist
@@ -44,17 +46,23 @@ cd $BASENAME/vsprojects
./convert2008to2005.sh
cd ..
-# Build the dist again in .tar.gz and .tar.bz2 formats.
-./configure
-make dist-gzip
-make dist-bzip2
+for LANG in $LANGUAGES; do
+ # Build the dist again in .tar.gz
+ ./configure DIST_LANG=$LANG
+ make dist-gzip
+ mv $BASENAME.tar.gz ../protobuf-$LANG-$VERSION.tar.gz
+done
# Convert all text files to use DOS-style line endings, then build a .zip
# distribution.
todos *.txt */*.txt
-make dist-zip
-# Clean up.
-mv $BASENAME.tar.gz $BASENAME.tar.bz2 $BASENAME.zip ..
+for LANG in $LANGUAGES; do
+ # Build the dist again in .zip
+ ./configure DIST_LANG=$LANG
+ make dist-zip
+ mv $BASENAME.zip ../protobuf-$LANG-$VERSION.zip
+done
+
cd ..
rm -rf $BASENAME
diff --git a/python/setup.py b/python/setup.py
index 69ffcd1d..cfe25cc0 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -163,7 +163,7 @@ if __name__ == '__main__':
))
setup(name = 'protobuf',
- version = '2.6.2-pre',
+ version = '3.0.0-pre',
packages = [ 'google' ],
namespace_packages = [ 'google' ],
test_suite = 'setup.MakeTestSuite',
diff --git a/ruby/README.md b/ruby/README.md
new file mode 100644
index 00000000..c966a103
--- /dev/null
+++ b/ruby/README.md
@@ -0,0 +1,34 @@
+This directory contains the Ruby extension that implements Protocol Buffers
+functionality in Ruby.
+
+The Ruby extension makes use of generated Ruby code that defines message and
+enum types in a Ruby DSL. You may write definitions in this DSL directly, but
+we recommend using protoc's Ruby generation support with .proto files. The
+build process in this directory only installs the extension; you need to
+install protoc as well to have Ruby code generation functionality.
+
+Installation
+------------
+
+To build this Ruby extension, you will need:
+
+* Rake
+* Bundler
+* Ruby development headers
+* a C compiler
+* the upb submodule
+
+First, ensure that upb/ is checked out:
+
+ $ cd .. # top level protobuf directory
+ $ git submodule init
+ $ git submodule update
+
+Then install the required Ruby gems:
+
+ $ sudo gem install bundler rake rake-compiler rspec rubygems-tasks
+
+Then build the Gem:
+
+ $ rake gem
+ $ gem install pkg/protobuf-$VERSION.gem
diff --git a/ruby/Rakefile b/ruby/Rakefile
new file mode 100644
index 00000000..b782b403
--- /dev/null
+++ b/ruby/Rakefile
@@ -0,0 +1,37 @@
+require "rake/extensiontask"
+require "rake/testtask"
+
+spec = Gem::Specification.new do |s|
+ s.name = "protobuf"
+ s.version = "2.6.2"
+ s.licenses = ["BSD"]
+ s.summary = "Protocol Buffers"
+ s.description = "Protocol Buffers are Google's data interchange format."
+ s.authors = ["Protobuf Authors"]
+ s.email = "protobuf@googlegroups.com"
+
+ s.files = ["lib/protobuf_c.so", "lib/protobuf.rb"]
+end
+
+Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
+ ext.lib_dir = "lib"
+ ext.config_script = "extconf.rb"
+end
+
+Rake::TestTask.new(:test => :build) do |t|
+ t.test_files = FileList["tests/*.rb"]
+end
+
+task :chmod do
+ File.chmod(0755, "lib/protobuf_c.so")
+end
+
+Gem::PackageTask.new(spec) do |pkg|
+end
+task :package => :chmod
+task :gem => :chmod
+
+task :build => [:clean, :compile]
+task :default => [:build]
+
+# vim:sw=2:et
diff --git a/ruby/ext/protobuf_c/defs.c b/ruby/ext/protobuf_c/defs.c
new file mode 100644
index 00000000..bb6f10e1
--- /dev/null
+++ b/ruby/ext/protobuf_c/defs.c
@@ -0,0 +1,1286 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Common utilities.
+// -----------------------------------------------------------------------------
+
+const char* kDescriptorInstanceVar = "descriptor";
+
+static const char* get_str(VALUE str) {
+ Check_Type(str, T_STRING);
+ return RSTRING_PTR(str);
+}
+
+static VALUE rb_str_maybe_null(const char* s) {
+ if (s == NULL) {
+ s = "";
+ }
+ return rb_str_new2(s);
+}
+
+static upb_def* check_notfrozen(const upb_def* def) {
+ if (upb_def_isfrozen(def)) {
+ rb_raise(rb_eRuntimeError,
+ "Attempt to modify a frozen descriptor. Once descriptors are "
+ "added to the descriptor pool, they may not be modified.");
+ }
+ return (upb_def*)def;
+}
+
+static upb_msgdef* check_msg_notfrozen(const upb_msgdef* def) {
+ return (upb_msgdef*)check_notfrozen((const upb_def*)def);
+}
+
+static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) {
+ return (upb_fielddef*)check_notfrozen((const upb_def*)def);
+}
+
+static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
+ return (upb_enumdef*)check_notfrozen((const upb_def*)def);
+}
+
+// -----------------------------------------------------------------------------
+// DescriptorPool.
+// -----------------------------------------------------------------------------
+
+#define DEFINE_CLASS(name, string_name) \
+ VALUE c ## name; \
+ const rb_data_type_t _ ## name ## _type = { \
+ string_name, \
+ { name ## _mark, name ## _free, NULL }, \
+ }; \
+ name* ruby_to_ ## name(VALUE val) { \
+ name* ret; \
+ TypedData_Get_Struct(val, name, &_ ## name ## _type, ret); \
+ return ret; \
+ } \
+
+#define DEFINE_SELF(type, var, rb_var) \
+ type* var = ruby_to_ ## type(rb_var);
+
+// Global singleton DescriptorPool. The user is free to create others, but this
+// is used by generated code.
+VALUE generated_pool;
+
+DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
+
+void DescriptorPool_mark(void* _self) {
+}
+
+void DescriptorPool_free(void* _self) {
+ DescriptorPool* self = _self;
+ upb_symtab_unref(self->symtab, &self->symtab);
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * DescriptorPool.new => pool
+ *
+ * Creates a new, empty, descriptor pool.
+ */
+VALUE DescriptorPool_alloc(VALUE klass) {
+ DescriptorPool* self = ALLOC(DescriptorPool);
+ self->symtab = upb_symtab_new(&self->symtab);
+ return TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
+}
+
+void DescriptorPool_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "DescriptorPool", rb_cObject);
+ rb_define_alloc_func(klass, DescriptorPool_alloc);
+ rb_define_method(klass, "add", DescriptorPool_add, 1);
+ rb_define_method(klass, "build", DescriptorPool_build, 0);
+ rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
+ rb_define_singleton_method(klass, "generated_pool",
+ DescriptorPool_generated_pool, 0);
+ cDescriptorPool = klass;
+ rb_gc_register_address(&cDescriptorPool);
+
+ generated_pool = rb_class_new_instance(0, NULL, klass);
+ rb_gc_register_address(&generated_pool);
+}
+
+static void add_descriptor_to_pool(DescriptorPool* self,
+ Descriptor* descriptor) {
+ CHECK_UPB(
+ upb_symtab_add(self->symtab, (upb_def**)&descriptor->msgdef, 1,
+ NULL, &status),
+ "Adding Descriptor to DescriptorPool failed");
+}
+
+static void add_enumdesc_to_pool(DescriptorPool* self,
+ EnumDescriptor* enumdesc) {
+ CHECK_UPB(
+ upb_symtab_add(self->symtab, (upb_def**)&enumdesc->enumdef, 1,
+ NULL, &status),
+ "Adding EnumDescriptor to DescriptorPool failed");
+}
+
+/*
+ * call-seq:
+ * DescriptorPool.add(descriptor)
+ *
+ * Adds the given Descriptor or EnumDescriptor to this pool. All references to
+ * other types in a Descriptor's fields must be resolvable within this pool or
+ * an exception will be raised.
+ */
+VALUE DescriptorPool_add(VALUE _self, VALUE def) {
+ DEFINE_SELF(DescriptorPool, self, _self);
+ VALUE def_klass = rb_obj_class(def);
+ if (def_klass == cDescriptor) {
+ add_descriptor_to_pool(self, ruby_to_Descriptor(def));
+ } else if (def_klass == cEnumDescriptor) {
+ add_enumdesc_to_pool(self, ruby_to_EnumDescriptor(def));
+ } else {
+ rb_raise(rb_eArgError,
+ "Second argument must be a Descriptor or EnumDescriptor.");
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * DescriptorPool.build(&block)
+ *
+ * Invokes the block with a Builder instance as self. All message and enum types
+ * added within the block are committed to the pool atomically, and may refer
+ * (co)recursively to each other. The user should call Builder#add_message and
+ * Builder#add_enum within the block as appropriate. This is the recommended,
+ * idiomatic way to define new message and enum types.
+ */
+VALUE DescriptorPool_build(VALUE _self) {
+ VALUE ctx = rb_class_new_instance(0, NULL, cBuilder);
+ VALUE block = rb_block_proc();
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+ rb_funcall(ctx, rb_intern("finalize_to_pool"), 1, _self);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * DescriptorPool.lookup(name) => descriptor
+ *
+ * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none
+ * exists with the given name.
+ */
+VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
+ DEFINE_SELF(DescriptorPool, self, _self);
+ const char* name_str = get_str(name);
+ const upb_def* def = upb_symtab_lookup(self->symtab, name_str);
+ if (!def) {
+ return Qnil;
+ }
+ return get_def_obj(def);
+}
+
+/*
+ * call-seq:
+ * DescriptorPool.generated_pool => descriptor_pool
+ *
+ * Class method that returns the global DescriptorPool. This is a singleton into
+ * which generated-code message and enum types are registered. The user may also
+ * register types in this pool for convenience so that they do not have to hold
+ * a reference to a private pool instance.
+ */
+VALUE DescriptorPool_generated_pool(VALUE _self) {
+ return generated_pool;
+}
+
+// -----------------------------------------------------------------------------
+// Descriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
+
+void Descriptor_mark(void* _self) {
+ Descriptor* self = _self;
+ rb_gc_mark(self->klass);
+}
+
+void Descriptor_free(void* _self) {
+ Descriptor* self = _self;
+ upb_msgdef_unref(self->msgdef, &self->msgdef);
+ if (self->layout) {
+ free_layout(self->layout);
+ }
+ if (self->fill_handlers) {
+ upb_handlers_unref(self->fill_handlers, &self->fill_handlers);
+ }
+ if (self->fill_method) {
+ upb_pbdecodermethod_unref(self->fill_method, &self->fill_method);
+ }
+ if (self->pb_serialize_handlers) {
+ upb_handlers_unref(self->pb_serialize_handlers,
+ &self->pb_serialize_handlers);
+ }
+ if (self->json_serialize_handlers) {
+ upb_handlers_unref(self->pb_serialize_handlers,
+ &self->json_serialize_handlers);
+ }
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * Descriptor.new => descriptor
+ *
+ * Creates a new, empty, message type descriptor. At a minimum, its name must be
+ * set before it is added to a pool. It cannot be used to create messages until
+ * it is added to a pool, after which it becomes immutable (as part of a
+ * finalization process).
+ */
+VALUE Descriptor_alloc(VALUE klass) {
+ Descriptor* self = ALLOC(Descriptor);
+ VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
+ self->msgdef = upb_msgdef_new(&self->msgdef);
+ self->klass = Qnil;
+ self->layout = NULL;
+ self->fill_handlers = NULL;
+ self->fill_method = NULL;
+ self->pb_serialize_handlers = NULL;
+ self->json_serialize_handlers = NULL;
+ return ret;
+}
+
+void Descriptor_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "Descriptor", rb_cObject);
+ rb_define_alloc_func(klass, Descriptor_alloc);
+ rb_define_method(klass, "each", Descriptor_each, 0);
+ rb_define_method(klass, "lookup", Descriptor_lookup, 1);
+ rb_define_method(klass, "add_field", Descriptor_add_field, 1);
+ rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
+ rb_define_method(klass, "name", Descriptor_name, 0);
+ rb_define_method(klass, "name=", Descriptor_name_set, 1);
+ rb_include_module(klass, rb_mEnumerable);
+ cDescriptor = klass;
+ rb_gc_register_address(&cDescriptor);
+}
+
+/*
+ * call-seq:
+ * Descriptor.name => name
+ *
+ * Returns the name of this message type as a fully-qualfied string (e.g.,
+ * My.Package.MessageType).
+ */
+VALUE Descriptor_name(VALUE _self) {
+ DEFINE_SELF(Descriptor, self, _self);
+ return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
+}
+
+/*
+ * call-seq:
+ * Descriptor.name = name
+ *
+ * Assigns a name to this message type. The descriptor must not have been added
+ * to a pool yet.
+ */
+VALUE Descriptor_name_set(VALUE _self, VALUE str) {
+ DEFINE_SELF(Descriptor, self, _self);
+ upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+ const char* name = get_str(str);
+ CHECK_UPB(
+ upb_msgdef_setfullname(mut_def, name, &status),
+ "Error setting Descriptor name");
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Descriptor.each(&block)
+ *
+ * Iterates over fields in this message type, yielding to the block on each one.
+ */
+VALUE Descriptor_each(VALUE _self) {
+ DEFINE_SELF(Descriptor, self, _self);
+
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, self->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ VALUE obj = get_def_obj(field);
+ rb_yield(obj);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Descriptor.lookup(name) => FieldDescriptor
+ *
+ * Returns the field descriptor for the field with the given name, if present,
+ * or nil if none.
+ */
+VALUE Descriptor_lookup(VALUE _self, VALUE name) {
+ DEFINE_SELF(Descriptor, self, _self);
+ const char* s = get_str(name);
+ const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s);
+ if (field == NULL) {
+ return Qnil;
+ }
+ return get_def_obj(field);
+}
+
+/*
+ * call-seq:
+ * Descriptor.add_field(field) => nil
+ *
+ * Adds the given FieldDescriptor to this message type. The descriptor must not
+ * have been added to a pool yet. Raises an exception if a field with the same
+ * name or number already exists. Sub-type references (e.g. for fields of type
+ * message) are not resolved at this point.
+ */
+VALUE Descriptor_add_field(VALUE _self, VALUE obj) {
+ DEFINE_SELF(Descriptor, self, _self);
+ upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
+ FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
+ upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
+ CHECK_UPB(
+ upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
+ "Adding field to Descriptor failed");
+ add_def_obj(def->fielddef, obj);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Descriptor.msgclass => message_klass
+ *
+ * Returns the Ruby class created for this message type. Valid only once the
+ * message type has been added to a pool.
+ */
+VALUE Descriptor_msgclass(VALUE _self) {
+ DEFINE_SELF(Descriptor, self, _self);
+ if (!upb_def_isfrozen((const upb_def*)self->msgdef)) {
+ rb_raise(rb_eRuntimeError,
+ "Cannot fetch message class from a Descriptor not yet in a pool.");
+ }
+ if (self->klass == Qnil) {
+ self->klass = build_class_from_descriptor(self);
+ }
+ return self->klass;
+}
+
+// -----------------------------------------------------------------------------
+// FieldDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
+
+void FieldDescriptor_mark(void* _self) {
+}
+
+void FieldDescriptor_free(void* _self) {
+ FieldDescriptor* self = _self;
+ upb_fielddef_unref(self->fielddef, &self->fielddef);
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.new => field
+ *
+ * Returns a new field descriptor. Its name, type, etc. must be set before it is
+ * added to a message type.
+ */
+VALUE FieldDescriptor_alloc(VALUE klass) {
+ FieldDescriptor* self = ALLOC(FieldDescriptor);
+ VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
+ upb_fielddef* fielddef = upb_fielddef_new(&self->fielddef);
+ upb_fielddef_setpacked(fielddef, false);
+ self->fielddef = fielddef;
+ return ret;
+}
+
+void FieldDescriptor_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "FieldDescriptor", rb_cObject);
+ rb_define_alloc_func(klass, FieldDescriptor_alloc);
+ rb_define_method(klass, "name", FieldDescriptor_name, 0);
+ rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
+ rb_define_method(klass, "type", FieldDescriptor_type, 0);
+ rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
+ rb_define_method(klass, "label", FieldDescriptor_label, 0);
+ rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
+ rb_define_method(klass, "number", FieldDescriptor_number, 0);
+ rb_define_method(klass, "number=", FieldDescriptor_number_set, 1);
+ rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
+ rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
+ rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
+ rb_define_method(klass, "get", FieldDescriptor_get, 1);
+ rb_define_method(klass, "set", FieldDescriptor_set, 2);
+ cFieldDescriptor = klass;
+ rb_gc_register_address(&cFieldDescriptor);
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.name => name
+ *
+ * Returns the name of this field.
+ */
+VALUE FieldDescriptor_name(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.name = name
+ *
+ * Sets the name of this field. Cannot be called once the containing message
+ * type, if any, is added to a pool.
+ */
+VALUE FieldDescriptor_name_set(VALUE _self, VALUE str) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+ const char* name = get_str(str);
+ CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
+ "Error setting FieldDescriptor name");
+ return Qnil;
+}
+
+upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
+ if (TYPE(type) != T_SYMBOL) {
+ rb_raise(rb_eArgError, "Expected symbol for field type.");
+ }
+
+ upb_fieldtype_t upb_type = -1;
+
+#define CONVERT(upb, ruby) \
+ if (SYM2ID(type) == rb_intern( # ruby )) { \
+ upb_type = UPB_TYPE_ ## upb; \
+ }
+
+ CONVERT(FLOAT, float);
+ CONVERT(DOUBLE, double);
+ CONVERT(BOOL, bool);
+ CONVERT(STRING, string);
+ CONVERT(BYTES, bytes);
+ CONVERT(MESSAGE, message);
+ CONVERT(ENUM, enum);
+ CONVERT(INT32, int32);
+ CONVERT(INT64, int64);
+ CONVERT(UINT32, uint32);
+ CONVERT(UINT64, uint64);
+
+#undef CONVERT
+
+ if (upb_type == -1) {
+ rb_raise(rb_eArgError, "Unknown field type.");
+ }
+
+ return upb_type;
+}
+
+VALUE fieldtype_to_ruby(upb_fieldtype_t type) {
+ switch (type) {
+#define CONVERT(upb, ruby) \
+ case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby ));
+ CONVERT(FLOAT, float);
+ CONVERT(DOUBLE, double);
+ CONVERT(BOOL, bool);
+ CONVERT(STRING, string);
+ CONVERT(BYTES, bytes);
+ CONVERT(MESSAGE, message);
+ CONVERT(ENUM, enum);
+ CONVERT(INT32, int32);
+ CONVERT(INT64, int64);
+ CONVERT(UINT32, uint32);
+ CONVERT(UINT64, uint64);
+#undef CONVERT
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.type => type
+ *
+ * Returns this field's type, as a Ruby symbol, or nil if not yet set.
+ *
+ * Valid field types are:
+ * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string,
+ * :bytes, :message.
+ */
+VALUE FieldDescriptor_type(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ if (!upb_fielddef_typeisset(self->fielddef)) {
+ return Qnil;
+ }
+ return fieldtype_to_ruby(upb_fielddef_type(self->fielddef));
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.type = type
+ *
+ * Sets this field's type. Cannot be called if field is part of a message type
+ * already in a pool.
+ */
+VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+ upb_fielddef_settype(mut_def, ruby_to_fieldtype(type));
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.label => label
+ *
+ * Returns this field's label (i.e., plurality), as a Ruby symbol.
+ *
+ * Valid field labels are:
+ * :optional, :repeated
+ */
+VALUE FieldDescriptor_label(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ switch (upb_fielddef_label(self->fielddef)) {
+#define CONVERT(upb, ruby) \
+ case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby ));
+
+ CONVERT(OPTIONAL, optional);
+ CONVERT(REQUIRED, required);
+ CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.label = label
+ *
+ * Sets the label on this field. Cannot be called if field is part of a message
+ * type already in a pool.
+ */
+VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+ if (TYPE(label) != T_SYMBOL) {
+ rb_raise(rb_eArgError, "Expected symbol for field label.");
+ }
+
+ upb_label_t upb_label = -1;
+
+#define CONVERT(upb, ruby) \
+ if (SYM2ID(label) == rb_intern( # ruby )) { \
+ upb_label = UPB_LABEL_ ## upb; \
+ }
+
+ CONVERT(OPTIONAL, optional);
+ CONVERT(REQUIRED, required);
+ CONVERT(REPEATED, repeated);
+
+#undef CONVERT
+
+ if (upb_label == -1) {
+ rb_raise(rb_eArgError, "Unknown field label.");
+ }
+
+ upb_fielddef_setlabel(mut_def, upb_label);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.number => number
+ *
+ * Returns the tag number for this field.
+ */
+VALUE FieldDescriptor_number(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ return INT2NUM(upb_fielddef_number(self->fielddef));
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.number = number
+ *
+ * Sets the tag number for this field. Cannot be called if field is part of a
+ * message type already in a pool.
+ */
+VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+ CHECK_UPB(upb_fielddef_setnumber(mut_def, NUM2INT(number), &status),
+ "Error setting field number");
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.submsg_name => submsg_name
+ *
+ * Returns the name of the message or enum type corresponding to this field, if
+ * it is a message or enum field (respectively), or nil otherwise. This type
+ * name will be resolved within the context of the pool to which the containing
+ * message type is added.
+ */
+VALUE FieldDescriptor_submsg_name(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ if (!upb_fielddef_hassubdef(self->fielddef)) {
+ return Qnil;
+ }
+ return rb_str_maybe_null(upb_fielddef_subdefname(self->fielddef));
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.submsg_name = submsg_name
+ *
+ * Sets the name of the message or enum type corresponding to this field, if it
+ * is a message or enum field (respectively). This type name will be resolved
+ * within the context of the pool to which the containing message type is added.
+ * Cannot be called on field that are not of message or enum type, or on fields
+ * that are part of a message type already added to a pool.
+ */
+VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
+ if (!upb_fielddef_hassubdef(self->fielddef)) {
+ rb_raise(rb_eTypeError, "FieldDescriptor does not have subdef.");
+ }
+ const char* str = get_str(value);
+ CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
+ "Error setting submessage name");
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.subtype => message_or_enum_descriptor
+ *
+ * Returns the message or enum descriptor corresponding to this field's type if
+ * it is a message or enum field, respectively, or nil otherwise. Cannot be
+ * called *until* the containing message type is added to a pool (and thus
+ * resolved).
+ */
+VALUE FieldDescriptor_subtype(VALUE _self) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ if (!upb_fielddef_hassubdef(self->fielddef)) {
+ return Qnil;
+ }
+ const upb_def* def = upb_fielddef_subdef(self->fielddef);
+ if (def == NULL) {
+ return Qnil;
+ }
+ return get_def_obj(def);
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.get(message) => value
+ *
+ * Returns the value set for this field on the given message. Raises an
+ * exception if message is of the wrong type.
+ */
+VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ MessageHeader* msg;
+ TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+ if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
+ rb_raise(rb_eTypeError, "get method called on wrong message type");
+ }
+ return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef);
+}
+
+/*
+ * call-seq:
+ * FieldDescriptor.set(message, value)
+ *
+ * Sets the value corresponding to this field to the given value on the given
+ * message. Raises an exception if message is of the wrong type. Performs the
+ * ordinary type-checks for field setting.
+ */
+VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
+ DEFINE_SELF(FieldDescriptor, self, _self);
+ MessageHeader* msg;
+ TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+ if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) {
+ rb_raise(rb_eTypeError, "set method called on wrong message type");
+ }
+ layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value);
+ return Qnil;
+}
+
+// -----------------------------------------------------------------------------
+// EnumDescriptor.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
+
+void EnumDescriptor_mark(void* _self) {
+ EnumDescriptor* self = _self;
+ rb_gc_mark(self->module);
+}
+
+void EnumDescriptor_free(void* _self) {
+ EnumDescriptor* self = _self;
+ upb_enumdef_unref(self->enumdef, &self->enumdef);
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.new => enum_descriptor
+ *
+ * Creates a new, empty, enum descriptor. Must be added to a pool before the
+ * enum type can be used. The enum type may only be modified prior to adding to
+ * a pool.
+ */
+VALUE EnumDescriptor_alloc(VALUE klass) {
+ EnumDescriptor* self = ALLOC(EnumDescriptor);
+ VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
+ self->enumdef = upb_enumdef_new(&self->enumdef);
+ self->module = Qnil;
+ return ret;
+}
+
+void EnumDescriptor_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "EnumDescriptor", rb_cObject);
+ rb_define_alloc_func(klass, EnumDescriptor_alloc);
+ rb_define_method(klass, "name", EnumDescriptor_name, 0);
+ rb_define_method(klass, "name=", EnumDescriptor_name_set, 1);
+ rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2);
+ rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
+ rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
+ rb_define_method(klass, "each", EnumDescriptor_each, 0);
+ rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0);
+ rb_include_module(klass, rb_mEnumerable);
+ cEnumDescriptor = klass;
+ rb_gc_register_address(&cEnumDescriptor);
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.name => name
+ *
+ * Returns the name of this enum type.
+ */
+VALUE EnumDescriptor_name(VALUE _self) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.name = name
+ *
+ * Sets the name of this enum type. Cannot be called if the enum type has
+ * already been added to a pool.
+ */
+VALUE EnumDescriptor_name_set(VALUE _self, VALUE str) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
+ const char* name = get_str(str);
+ CHECK_UPB(upb_enumdef_setfullname(mut_def, name, &status),
+ "Error setting EnumDescriptor name");
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.add_value(key, value)
+ *
+ * Adds a new key => value mapping to this enum type. Key must be given as a
+ * Ruby symbol. Cannot be called if the enum type has already been added to a
+ * pool. Will raise an exception if the key or value is already in use.
+ */
+VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
+ const char* name_str = rb_id2name(SYM2ID(name));
+ int32_t val = NUM2INT(number);
+ CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status),
+ "Error adding value to enum");
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.lookup_name(name) => value
+ *
+ * Returns the numeric value corresponding to the given key name (as a Ruby
+ * symbol), or nil if none.
+ */
+VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ const char* name_str= rb_id2name(SYM2ID(name));
+ int32_t val = 0;
+ if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) {
+ return INT2NUM(val);
+ } else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.lookup_value(name) => value
+ *
+ * Returns the key name (as a Ruby symbol) corresponding to the integer value,
+ * or nil if none.
+ */
+VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ int32_t val = NUM2INT(number);
+ const char* name = upb_enumdef_iton(self->enumdef, val);
+ if (name != NULL) {
+ return ID2SYM(rb_intern(name));
+ } else {
+ return Qnil;
+ }
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.each(&block)
+ *
+ * Iterates over key => value mappings in this enum's definition, yielding to
+ * the block with (key, value) arguments for each one.
+ */
+VALUE EnumDescriptor_each(VALUE _self) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+
+ upb_enum_iter it;
+ for (upb_enum_begin(&it, self->enumdef);
+ !upb_enum_done(&it);
+ upb_enum_next(&it)) {
+ VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it)));
+ VALUE number = INT2NUM(upb_enum_iter_number(&it));
+ rb_yield_values(2, key, number);
+ }
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * EnumDescriptor.enummodule => module
+ *
+ * Returns the Ruby module corresponding to this enum type. Cannot be called
+ * until the enum descriptor has been added to a pool.
+ */
+VALUE EnumDescriptor_enummodule(VALUE _self) {
+ DEFINE_SELF(EnumDescriptor, self, _self);
+ if (!upb_def_isfrozen((const upb_def*)self->enumdef)) {
+ rb_raise(rb_eRuntimeError,
+ "Cannot fetch enum module from an EnumDescriptor not yet "
+ "in a pool.");
+ }
+ if (self->module == Qnil) {
+ self->module = build_module_from_enumdesc(self);
+ }
+ return self->module;
+}
+
+// -----------------------------------------------------------------------------
+// MessageBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(MessageBuilderContext,
+ "Google::Protobuf::Internal::MessageBuilderContext");
+
+void MessageBuilderContext_mark(void* _self) {
+ MessageBuilderContext* self = _self;
+ rb_gc_mark(self->descriptor);
+}
+
+void MessageBuilderContext_free(void* _self) {
+ MessageBuilderContext* self = _self;
+ xfree(self);
+}
+
+VALUE MessageBuilderContext_alloc(VALUE klass) {
+ MessageBuilderContext* self = ALLOC(MessageBuilderContext);
+ VALUE ret = TypedData_Wrap_Struct(
+ klass, &_MessageBuilderContext_type, self);
+ self->descriptor = Qnil;
+ return ret;
+}
+
+void MessageBuilderContext_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "MessageBuilderContext", rb_cObject);
+ rb_define_alloc_func(klass, MessageBuilderContext_alloc);
+ rb_define_method(klass, "initialize",
+ MessageBuilderContext_initialize, 1);
+ rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
+ rb_define_method(klass, "required", MessageBuilderContext_required, -1);
+ rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
+ cMessageBuilderContext = klass;
+ rb_gc_register_address(&cMessageBuilderContext);
+}
+
+/*
+ * call-seq:
+ * MessageBuilderContext.new(desc) => context
+ *
+ * Create a new builder context around the given message descriptor. This class
+ * is intended to serve as a DSL context to be used with #instance_eval.
+ */
+VALUE MessageBuilderContext_initialize(VALUE _self, VALUE msgdef) {
+ DEFINE_SELF(MessageBuilderContext, self, _self);
+ self->descriptor = msgdef;
+ return Qnil;
+}
+
+static VALUE msgdef_add_field(VALUE msgdef,
+ const char* label, VALUE name,
+ VALUE type, VALUE number,
+ VALUE type_class) {
+ VALUE fielddef = rb_class_new_instance(0, NULL, cFieldDescriptor);
+ VALUE name_str = rb_str_new2(rb_id2name(SYM2ID(name)));
+
+ rb_funcall(fielddef, rb_intern("label="), 1, ID2SYM(rb_intern(label)));
+ rb_funcall(fielddef, rb_intern("name="), 1, name_str);
+ rb_funcall(fielddef, rb_intern("type="), 1, type);
+ rb_funcall(fielddef, rb_intern("number="), 1, number);
+
+ if (type_class != Qnil) {
+ if (TYPE(type_class) != T_STRING) {
+ rb_raise(rb_eArgError, "Expected string for type class");
+ }
+ // Make it an absolute type name by prepending a dot.
+ type_class = rb_str_append(rb_str_new2("."), type_class);
+ rb_funcall(fielddef, rb_intern("submsg_name="), 1, type_class);
+ }
+
+ rb_funcall(msgdef, rb_intern("add_field"), 1, fielddef);
+ return fielddef;
+}
+
+/*
+ * call-seq:
+ * MessageBuilderContext.optional(name, type, number, type_class = nil)
+ *
+ * Defines a new optional field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
+ DEFINE_SELF(MessageBuilderContext, self, _self);
+
+ if (argc < 3) {
+ rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+ }
+ VALUE name = argv[0];
+ VALUE type = argv[1];
+ VALUE number = argv[2];
+ VALUE type_class = (argc > 3) ? argv[3] : Qnil;
+
+ return msgdef_add_field(self->descriptor, "optional",
+ name, type, number, type_class);
+}
+
+/*
+ * call-seq:
+ * MessageBuilderContext.required(name, type, number, type_class = nil)
+ *
+ * Defines a new required field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ *
+ * Proto3 does not have required fields, but this method exists for
+ * completeness. Any attempt to add a message type with required fields to a
+ * pool will currently result in an error.
+ */
+VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
+ DEFINE_SELF(MessageBuilderContext, self, _self);
+
+ if (argc < 3) {
+ rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+ }
+ VALUE name = argv[0];
+ VALUE type = argv[1];
+ VALUE number = argv[2];
+ VALUE type_class = (argc > 3) ? argv[3] : Qnil;
+
+ return msgdef_add_field(self->descriptor, "required",
+ name, type, number, type_class);
+}
+
+/*
+ * call-seq:
+ * MessageBuilderContext.repeated(name, type, number, type_class = nil)
+ *
+ * Defines a new repeated field on this message type with the given type, tag
+ * number, and type class (for message and enum fields). The type must be a Ruby
+ * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a
+ * string, if present (as accepted by FieldDescriptor#submsg_name=).
+ */
+VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
+ DEFINE_SELF(MessageBuilderContext, self, _self);
+
+ if (argc < 3) {
+ rb_raise(rb_eArgError, "Expected at least 3 arguments.");
+ }
+ VALUE name = argv[0];
+ VALUE type = argv[1];
+ VALUE number = argv[2];
+ VALUE type_class = (argc > 3) ? argv[3] : Qnil;
+
+ return msgdef_add_field(self->descriptor, "repeated",
+ name, type, number, type_class);
+}
+
+// -----------------------------------------------------------------------------
+// EnumBuilderContext.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(EnumBuilderContext,
+ "Google::Protobuf::Internal::EnumBuilderContext");
+
+void EnumBuilderContext_mark(void* _self) {
+ EnumBuilderContext* self = _self;
+ rb_gc_mark(self->enumdesc);
+}
+
+void EnumBuilderContext_free(void* _self) {
+ EnumBuilderContext* self = _self;
+ xfree(self);
+}
+
+VALUE EnumBuilderContext_alloc(VALUE klass) {
+ EnumBuilderContext* self = ALLOC(EnumBuilderContext);
+ VALUE ret = TypedData_Wrap_Struct(
+ klass, &_EnumBuilderContext_type, self);
+ self->enumdesc = Qnil;
+ return ret;
+}
+
+void EnumBuilderContext_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "EnumBuilderContext", rb_cObject);
+ rb_define_alloc_func(klass, EnumBuilderContext_alloc);
+ rb_define_method(klass, "initialize",
+ EnumBuilderContext_initialize, 1);
+ rb_define_method(klass, "value", EnumBuilderContext_value, 2);
+ cEnumBuilderContext = klass;
+ rb_gc_register_address(&cEnumBuilderContext);
+}
+
+/*
+ * call-seq:
+ * EnumBuilderContext.new(enumdesc) => context
+ *
+ * Create a new builder context around the given enum descriptor. This class is
+ * intended to serve as a DSL context to be used with #instance_eval.
+ */
+VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdef) {
+ DEFINE_SELF(EnumBuilderContext, self, _self);
+ self->enumdesc = enumdef;
+ return Qnil;
+}
+
+static VALUE enumdef_add_value(VALUE enumdef,
+ VALUE name, VALUE number) {
+ rb_funcall(enumdef, rb_intern("add_value"), 2, name, number);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * EnumBuilder.add_value(name, number)
+ *
+ * Adds the given name => number mapping to the enum type. Name must be a Ruby
+ * symbol.
+ */
+VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
+ DEFINE_SELF(EnumBuilderContext, self, _self);
+ return enumdef_add_value(self->enumdesc, name, number);
+}
+
+// -----------------------------------------------------------------------------
+// Builder.
+// -----------------------------------------------------------------------------
+
+DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
+
+void Builder_mark(void* _self) {
+ Builder* self = _self;
+ rb_gc_mark(self->pending_list);
+}
+
+void Builder_free(void* _self) {
+ Builder* self = _self;
+ xfree(self->defs);
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * Builder.new => builder
+ *
+ * Creates a new Builder. A Builder can accumulate a set of new message and enum
+ * descriptors and atomically register them into a pool in a way that allows for
+ * (co)recursive type references.
+ */
+VALUE Builder_alloc(VALUE klass) {
+ Builder* self = ALLOC(Builder);
+ VALUE ret = TypedData_Wrap_Struct(
+ klass, &_Builder_type, self);
+ self->pending_list = rb_ary_new();
+ self->defs = NULL;
+ return ret;
+}
+
+void Builder_register(VALUE module) {
+ VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
+ rb_define_alloc_func(klass, Builder_alloc);
+ rb_define_method(klass, "add_message", Builder_add_message, 1);
+ rb_define_method(klass, "add_enum", Builder_add_enum, 1);
+ rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
+ cBuilder = klass;
+ rb_gc_register_address(&cBuilder);
+}
+
+/*
+ * call-seq:
+ * Builder.add_message(name, &block)
+ *
+ * Creates a new, empty descriptor with the given name, and invokes the block in
+ * the context of a MessageBuilderContext on that descriptor. The block can then
+ * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated
+ * methods to define the message fields.
+ *
+ * This is the recommended, idiomatic way to build message definitions.
+ */
+VALUE Builder_add_message(VALUE _self, VALUE name) {
+ DEFINE_SELF(Builder, self, _self);
+ VALUE msgdef = rb_class_new_instance(0, NULL, cDescriptor);
+ VALUE ctx = rb_class_new_instance(1, &msgdef, cMessageBuilderContext);
+ VALUE block = rb_block_proc();
+ rb_funcall(msgdef, rb_intern("name="), 1, name);
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+ rb_ary_push(self->pending_list, msgdef);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Builder.add_enum(name, &block)
+ *
+ * Creates a new, empty enum descriptor with the given name, and invokes the block in
+ * the context of an EnumBuilderContext on that descriptor. The block can then
+ * call EnumBuilderContext#add_value to define the enum values.
+ *
+ * This is the recommended, idiomatic way to build enum definitions.
+ */
+VALUE Builder_add_enum(VALUE _self, VALUE name) {
+ DEFINE_SELF(Builder, self, _self);
+ VALUE enumdef = rb_class_new_instance(0, NULL, cEnumDescriptor);
+ VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
+ VALUE block = rb_block_proc();
+ rb_funcall(enumdef, rb_intern("name="), 1, name);
+ rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
+ rb_ary_push(self->pending_list, enumdef);
+ return Qnil;
+}
+
+static void validate_msgdef(const upb_msgdef* msgdef) {
+ // Verify that no required fields exist. proto3 does not support these.
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
+ rb_raise(rb_eTypeError, "Required fields are unsupported in proto3.");
+ }
+ }
+}
+
+static void validate_enumdef(const upb_enumdef* enumdef) {
+ // Verify that an entry exists with integer value 0. (This is the default
+ // value.)
+ const char* lookup = upb_enumdef_iton(enumdef, 0);
+ if (lookup == NULL) {
+ rb_raise(rb_eTypeError,
+ "Enum definition does not contain a value for '0'.");
+ }
+}
+
+/*
+ * call-seq:
+ * Builder.finalize_to_pool(pool)
+ *
+ * Adds all accumulated message and enum descriptors created in this builder
+ * context to the given pool. The operation occurs atomically, and all
+ * descriptors can refer to each other (including in cycles). This is the only
+ * way to build (co)recursive message definitions.
+ *
+ * This method is usually called automatically by DescriptorPool#build after it
+ * invokes the given user block in the context of the builder. The user should
+ * not normally need to call this manually because a Builder is not normally
+ * created manually.
+ */
+VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) {
+ DEFINE_SELF(Builder, self, _self);
+
+ DescriptorPool* pool = ruby_to_DescriptorPool(pool_rb);
+
+ REALLOC_N(self->defs, upb_def*, RARRAY_LEN(self->pending_list));
+
+ for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
+ VALUE def_rb = rb_ary_entry(self->pending_list, i);
+ if (CLASS_OF(def_rb) == cDescriptor) {
+ self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef;
+ validate_msgdef((const upb_msgdef*)self->defs[i]);
+ } else if (CLASS_OF(def_rb) == cEnumDescriptor) {
+ self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef;
+ validate_enumdef((const upb_enumdef*)self->defs[i]);
+ }
+ }
+
+ CHECK_UPB(upb_symtab_add(pool->symtab, (upb_def**)self->defs,
+ RARRAY_LEN(self->pending_list), NULL, &status),
+ "Unable to add defs to DescriptorPool");
+
+ for (int i = 0; i < RARRAY_LEN(self->pending_list); i++) {
+ VALUE def_rb = rb_ary_entry(self->pending_list, i);
+ add_def_obj(self->defs[i], def_rb);
+ }
+
+ self->pending_list = rb_ary_new();
+ return Qnil;
+}
diff --git a/ruby/ext/protobuf_c/encode_decode.c b/ruby/ext/protobuf_c/encode_decode.c
new file mode 100644
index 00000000..8aba3c9e
--- /dev/null
+++ b/ruby/ext/protobuf_c/encode_decode.c
@@ -0,0 +1,755 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Parsing.
+// -----------------------------------------------------------------------------
+
+#define DEREF(msg, ofs, type) *(type*)(((uint8_t *)msg) + ofs)
+
+// Creates a handlerdata that simply contains the offset for this field.
+static const void* newhandlerdata(upb_handlers* h, uint32_t ofs) {
+ size_t* hd_ofs = ALLOC(size_t);
+ *hd_ofs = ofs;
+ upb_handlers_addcleanup(h, hd_ofs, free);
+ return hd_ofs;
+}
+
+typedef struct {
+ size_t ofs;
+ const upb_msgdef *md;
+} submsg_handlerdata_t;
+
+// Creates a handlerdata that contains offset and submessage type information.
+static const void *newsubmsghandlerdata(upb_handlers* h, uint32_t ofs,
+ const upb_fielddef* f) {
+ submsg_handlerdata_t *hd = ALLOC(submsg_handlerdata_t);
+ hd->ofs = ofs;
+ hd->md = upb_fielddef_msgsubdef(f);
+ upb_handlers_addcleanup(h, hd, free);
+ return hd;
+}
+
+// A handler that starts a repeated field. Gets the Repeated*Field instance for
+// this field (such an instance always exists even in an empty message).
+static void *startseq_handler(void* closure, const void* hd) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ return (void*)DEREF(Message_data(msg), *ofs, VALUE);
+}
+
+// Handlers that append primitive values to a repeated field (a regular Ruby
+// array for now).
+#define DEFINE_APPEND_HANDLER(type, ctype) \
+ static bool append##type##_handler(void *closure, const void *hd, \
+ ctype val) { \
+ VALUE ary = (VALUE)closure; \
+ RepeatedField_push_native(ary, &val); \
+ return true; \
+ }
+
+DEFINE_APPEND_HANDLER(bool, bool)
+DEFINE_APPEND_HANDLER(int32, int32_t)
+DEFINE_APPEND_HANDLER(uint32, uint32_t)
+DEFINE_APPEND_HANDLER(float, float)
+DEFINE_APPEND_HANDLER(int64, int64_t)
+DEFINE_APPEND_HANDLER(uint64, uint64_t)
+DEFINE_APPEND_HANDLER(double, double)
+
+// Appends a string to a repeated field (a regular Ruby array for now).
+static void* appendstr_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ VALUE ary = (VALUE)closure;
+ VALUE str = rb_str_new2("");
+ rb_enc_associate(str, kRubyStringUtf8Encoding);
+ RepeatedField_push(ary, str);
+ return (void*)str;
+}
+
+// Appends a 'bytes' string to a repeated field (a regular Ruby array for now).
+static void* appendbytes_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ VALUE ary = (VALUE)closure;
+ VALUE str = rb_str_new2("");
+ rb_enc_associate(str, kRubyString8bitEncoding);
+ RepeatedField_push(ary, str);
+ return (void*)str;
+}
+
+// Sets a non-repeated string field in a message.
+static void* str_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ VALUE str = rb_str_new2("");
+ rb_enc_associate(str, kRubyStringUtf8Encoding);
+ DEREF(Message_data(msg), *ofs, VALUE) = str;
+ return (void*)str;
+}
+
+// Sets a non-repeated 'bytes' field in a message.
+static void* bytes_handler(void *closure,
+ const void *hd,
+ size_t size_hint) {
+ MessageHeader* msg = closure;
+ const size_t *ofs = hd;
+ VALUE str = rb_str_new2("");
+ rb_enc_associate(str, kRubyString8bitEncoding);
+ DEREF(Message_data(msg), *ofs, VALUE) = str;
+ return (void*)str;
+}
+
+static size_t stringdata_handler(void* closure, const void* hd,
+ const char* str, size_t len,
+ const upb_bufhandle* handle) {
+ VALUE rb_str = (VALUE)closure;
+ rb_str_cat(rb_str, str, len);
+ return len;
+}
+
+// Appends a submessage to a repeated field (a regular Ruby array for now).
+static void *appendsubmsg_handler(void *closure, const void *hd) {
+ VALUE ary = (VALUE)closure;
+ const submsg_handlerdata_t *submsgdata = hd;
+ VALUE subdesc =
+ get_def_obj((void*)submsgdata->md);
+ VALUE subklass = Descriptor_msgclass(subdesc);
+
+ VALUE submsg_rb = rb_class_new_instance(0, NULL, subklass);
+ RepeatedField_push(ary, submsg_rb);
+
+ MessageHeader* submsg;
+ TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+ return submsg;
+}
+
+// Sets a non-repeated submessage field in a message.
+static void *submsg_handler(void *closure, const void *hd) {
+ MessageHeader* msg = closure;
+ const submsg_handlerdata_t* submsgdata = hd;
+ VALUE subdesc =
+ get_def_obj((void*)submsgdata->md);
+ VALUE subklass = Descriptor_msgclass(subdesc);
+
+ if (DEREF(Message_data(msg), submsgdata->ofs, VALUE) == Qnil) {
+ DEREF(Message_data(msg), submsgdata->ofs, VALUE) =
+ rb_class_new_instance(0, NULL, subklass);
+ }
+
+ VALUE submsg_rb = DEREF(Message_data(msg), submsgdata->ofs, VALUE);
+ MessageHeader* submsg;
+ TypedData_Get_Struct(submsg_rb, MessageHeader, &Message_type, submsg);
+ return submsg;
+}
+
+static void add_handlers_for_message(const void *closure, upb_handlers *h) {
+ Descriptor* desc = ruby_to_Descriptor(
+ get_def_obj((void*)upb_handlers_msgdef(h)));
+ // Ensure layout exists. We may be invoked to create handlers for a given
+ // message if we are included as a submsg of another message type before our
+ // class is actually built, so to work around this, we just create the layout
+ // (and handlers, in the class-building function) on-demand.
+ if (desc->layout == NULL) {
+ desc->layout = create_layout(desc->msgdef);
+ }
+
+ upb_msg_iter i;
+
+ for (upb_msg_begin(&i, desc->msgdef);
+ !upb_msg_done(&i);
+ upb_msg_next(&i)) {
+ const upb_fielddef *f = upb_msg_iter_field(&i);
+ size_t offset = desc->layout->offsets[upb_fielddef_index(f)];
+
+ if (upb_fielddef_isseq(f)) {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+ upb_handlers_setstartseq(h, f, startseq_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+
+ switch (upb_fielddef_type(f)) {
+
+#define SET_HANDLER(utype, ltype) \
+ case utype: \
+ upb_handlers_set##ltype(h, f, append##ltype##_handler, NULL); \
+ break;
+
+ SET_HANDLER(UPB_TYPE_BOOL, bool);
+ SET_HANDLER(UPB_TYPE_INT32, int32);
+ SET_HANDLER(UPB_TYPE_UINT32, uint32);
+ SET_HANDLER(UPB_TYPE_ENUM, int32);
+ SET_HANDLER(UPB_TYPE_FLOAT, float);
+ SET_HANDLER(UPB_TYPE_INT64, int64);
+ SET_HANDLER(UPB_TYPE_UINT64, uint64);
+ SET_HANDLER(UPB_TYPE_DOUBLE, double);
+
+#undef SET_HANDLER
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+ upb_handlers_setstartstr(h, f, is_bytes ?
+ appendbytes_handler : appendstr_handler,
+ NULL);
+ upb_handlers_setstring(h, f, stringdata_handler, NULL);
+ }
+ case UPB_TYPE_MESSAGE: {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, 0, f));
+ upb_handlers_setstartsubmsg(h, f, appendsubmsg_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ }
+ }
+
+ switch (upb_fielddef_type(f)) {
+ case UPB_TYPE_BOOL:
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_FLOAT:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT64:
+ case UPB_TYPE_DOUBLE:
+ // The shim writes directly at the given offset (instead of using
+ // DEREF()) so we need to add the msg overhead.
+ upb_shim_set(h, f, offset + sizeof(MessageHeader), -1);
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ bool is_bytes = upb_fielddef_type(f) == UPB_TYPE_BYTES;
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, offset));
+ upb_handlers_setstartstr(h, f,
+ is_bytes ? bytes_handler : str_handler,
+ &attr);
+ upb_handlers_setstring(h, f, stringdata_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
+ upb_handlerattr_sethandlerdata(&attr, newsubmsghandlerdata(h, offset, f));
+ upb_handlers_setstartsubmsg(h, f, submsg_handler, &attr);
+ upb_handlerattr_uninit(&attr);
+ break;
+ }
+ }
+ }
+}
+
+// Creates upb handlers for populating a message.
+static const upb_handlers *new_fill_handlers(Descriptor* desc,
+ const void* owner) {
+ // TODO(cfallin, haberman): once upb gets a caching/memoization layer for
+ // handlers, reuse subdef handlers so that e.g. if we already parse
+ // B-with-field-of-type-C, we don't have to rebuild the whole hierarchy to
+ // parse A-with-field-of-type-B-with-field-of-type-C.
+ return upb_handlers_newfrozen(desc->msgdef, owner,
+ add_handlers_for_message, NULL);
+}
+
+// Constructs the handlers for filling a message's data into an in-memory
+// object.
+const upb_handlers* get_fill_handlers(Descriptor* desc) {
+ if (!desc->fill_handlers) {
+ desc->fill_handlers =
+ new_fill_handlers(desc, &desc->fill_handlers);
+ }
+ return desc->fill_handlers;
+}
+
+// Constructs the upb decoder method for parsing messages of this type.
+// This is called from the message class creation code.
+const upb_pbdecodermethod *new_fillmsg_decodermethod(Descriptor* desc,
+ const void* owner) {
+ const upb_handlers* handlers = get_fill_handlers(desc);
+ upb_pbdecodermethodopts opts;
+ upb_pbdecodermethodopts_init(&opts, handlers);
+
+ const upb_pbdecodermethod *ret = upb_pbdecodermethod_new(&opts, owner);
+ return ret;
+}
+
+static const upb_pbdecodermethod *msgdef_decodermethod(Descriptor* desc) {
+ if (desc->fill_method == NULL) {
+ desc->fill_method = new_fillmsg_decodermethod(
+ desc, &desc->fill_method);
+ }
+ return desc->fill_method;
+}
+
+/*
+ * call-seq:
+ * MessageClass.decode(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+VALUE Message_decode(VALUE klass, VALUE data) {
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
+ VALUE msgklass = Descriptor_msgclass(descriptor);
+
+ if (TYPE(data) != T_STRING) {
+ rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
+ }
+
+ VALUE msg_rb = rb_class_new_instance(0, NULL, msgklass);
+ MessageHeader* msg;
+ TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+
+ const upb_pbdecodermethod* method = msgdef_decodermethod(desc);
+ const upb_handlers* h = upb_pbdecodermethod_desthandlers(method);
+ upb_pbdecoder decoder;
+ upb_sink sink;
+ upb_status status = UPB_STATUS_INIT;
+
+ upb_pbdecoder_init(&decoder, method, &status);
+ upb_sink_reset(&sink, h, msg);
+ upb_pbdecoder_resetoutput(&decoder, &sink);
+ upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
+ upb_pbdecoder_input(&decoder));
+
+ upb_pbdecoder_uninit(&decoder);
+ if (!upb_ok(&status)) {
+ rb_raise(rb_eRuntimeError, "Error occurred during parsing: %s.",
+ upb_status_errmsg(&status));
+ }
+
+ return msg_rb;
+}
+
+/*
+ * call-seq:
+ * MessageClass.decode_json(data) => message
+ *
+ * Decodes the given data (as a string containing bytes in protocol buffers wire
+ * format) under the interpretration given by this message class's definition
+ * and returns a message object with the corresponding field values.
+ */
+VALUE Message_decode_json(VALUE klass, VALUE data) {
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
+ VALUE msgklass = Descriptor_msgclass(descriptor);
+
+ if (TYPE(data) != T_STRING) {
+ rb_raise(rb_eArgError, "Expected string for JSON data.");
+ }
+ // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
+ // convert, because string handlers pass data directly to message string
+ // fields.
+
+ VALUE msg_rb = rb_class_new_instance(0, NULL, msgklass);
+ MessageHeader* msg;
+ TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+
+ upb_status status = UPB_STATUS_INIT;
+ upb_json_parser parser;
+ upb_json_parser_init(&parser, &status);
+
+ upb_sink sink;
+ upb_sink_reset(&sink, get_fill_handlers(desc), msg);
+ upb_json_parser_resetoutput(&parser, &sink);
+ upb_bufsrc_putbuf(RSTRING_PTR(data), RSTRING_LEN(data),
+ upb_json_parser_input(&parser));
+
+ upb_json_parser_uninit(&parser);
+ if (!upb_ok(&status)) {
+ rb_raise(rb_eRuntimeError, "Error occurred during parsing: %s.",
+ upb_status_errmsg(&status));
+ }
+
+ return msg_rb;
+}
+
+// -----------------------------------------------------------------------------
+// Serializing.
+// -----------------------------------------------------------------------------
+//
+// The code below also comes from upb's prototype Ruby binding, developed by
+// haberman@.
+
+/* stringsink *****************************************************************/
+
+// This should probably be factored into a common upb component.
+
+typedef struct {
+ upb_byteshandler handler;
+ upb_bytessink sink;
+ char *ptr;
+ size_t len, size;
+} stringsink;
+
+static void *stringsink_start(void *_sink, const void *hd, size_t size_hint) {
+ stringsink *sink = _sink;
+ sink->len = 0;
+ return sink;
+}
+
+static size_t stringsink_string(void *_sink, const void *hd, const char *ptr,
+ size_t len, const upb_bufhandle *handle) {
+ UPB_UNUSED(hd);
+ UPB_UNUSED(handle);
+
+ stringsink *sink = _sink;
+ size_t new_size = sink->size;
+
+ while (sink->len + len > new_size) {
+ new_size *= 2;
+ }
+
+ if (new_size != sink->size) {
+ sink->ptr = realloc(sink->ptr, new_size);
+ sink->size = new_size;
+ }
+
+ memcpy(sink->ptr + sink->len, ptr, len);
+ sink->len += len;
+
+ return len;
+}
+
+void stringsink_init(stringsink *sink) {
+ upb_byteshandler_init(&sink->handler);
+ upb_byteshandler_setstartstr(&sink->handler, stringsink_start, NULL);
+ upb_byteshandler_setstring(&sink->handler, stringsink_string, NULL);
+
+ upb_bytessink_reset(&sink->sink, &sink->handler, sink);
+
+ sink->size = 32;
+ sink->ptr = malloc(sink->size);
+ sink->len = 0;
+}
+
+void stringsink_uninit(stringsink *sink) {
+ free(sink->ptr);
+}
+
+/* msgvisitor *****************************************************************/
+
+// TODO: If/when we support proto2 semantics in addition to the current proto3
+// semantics, which means that we have true field presence, we will want to
+// modify msgvisitor so that it emits all present fields rather than all
+// non-default-value fields.
+//
+// Likewise, when implementing JSON serialization, we may need to have a
+// 'verbose' mode that outputs all fields and a 'concise' mode that outputs only
+// those with non-default values.
+
+static void putmsg(VALUE msg, const Descriptor* desc,
+ upb_sink *sink, int depth);
+
+static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
+ upb_selector_t ret;
+ bool ok = upb_handlers_getselector(f, type, &ret);
+ UPB_ASSERT_VAR(ok, ok);
+ return ret;
+}
+
+static void putstr(VALUE str, const upb_fielddef *f, upb_sink *sink) {
+ if (str == Qnil) return;
+
+ assert(BUILTIN_TYPE(str) == RUBY_T_STRING);
+ upb_sink subsink;
+
+ // Ensure that the string has the correct encoding. We also check at field-set
+ // time, but the user may have mutated the string object since then.
+ native_slot_validate_string_encoding(upb_fielddef_type(f), str);
+
+ upb_sink_startstr(sink, getsel(f, UPB_HANDLER_STARTSTR), RSTRING_LEN(str),
+ &subsink);
+ upb_sink_putstring(&subsink, getsel(f, UPB_HANDLER_STRING), RSTRING_PTR(str),
+ RSTRING_LEN(str), NULL);
+ upb_sink_endstr(sink, getsel(f, UPB_HANDLER_ENDSTR));
+}
+
+static void putsubmsg(VALUE submsg, const upb_fielddef *f, upb_sink *sink,
+ int depth) {
+ if (submsg == Qnil) return;
+
+ upb_sink subsink;
+ VALUE descriptor = rb_iv_get(submsg, kDescriptorInstanceVar);
+ Descriptor* subdesc = ruby_to_Descriptor(descriptor);
+
+ upb_sink_startsubmsg(sink, getsel(f, UPB_HANDLER_STARTSUBMSG), &subsink);
+ putmsg(submsg, subdesc, &subsink, depth + 1);
+ upb_sink_endsubmsg(sink, getsel(f, UPB_HANDLER_ENDSUBMSG));
+}
+
+static void putary(VALUE ary, const upb_fielddef *f, upb_sink *sink,
+ int depth) {
+ if (ary == Qnil) return;
+
+ upb_sink subsink;
+
+ upb_sink_startseq(sink, getsel(f, UPB_HANDLER_STARTSEQ), &subsink);
+
+ upb_fieldtype_t type = upb_fielddef_type(f);
+ upb_selector_t sel = 0;
+ if (upb_fielddef_isprimitive(f)) {
+ sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+ }
+
+ int size = NUM2INT(RepeatedField_length(ary));
+ for (int i = 0; i < size; i++) {
+ void* memory = RepeatedField_index_native(ary, i);
+ switch (type) {
+#define T(upbtypeconst, upbtype, ctype) \
+ case upbtypeconst: \
+ upb_sink_put##upbtype(&subsink, sel, *((ctype *)memory)); \
+ break;
+
+ T(UPB_TYPE_FLOAT, float, float)
+ T(UPB_TYPE_DOUBLE, double, double)
+ T(UPB_TYPE_BOOL, bool, int8_t)
+ case UPB_TYPE_ENUM:
+ T(UPB_TYPE_INT32, int32, int32_t)
+ T(UPB_TYPE_UINT32, uint32, uint32_t)
+ T(UPB_TYPE_INT64, int64, int64_t)
+ T(UPB_TYPE_UINT64, uint64, uint64_t)
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ putstr(*((VALUE *)memory), f, &subsink);
+ break;
+ case UPB_TYPE_MESSAGE:
+ putsubmsg(*((VALUE *)memory), f, &subsink, depth);
+ break;
+
+#undef T
+
+ }
+ }
+ upb_sink_endseq(sink, getsel(f, UPB_HANDLER_ENDSEQ));
+}
+
+static void putmsg(VALUE msg_rb, const Descriptor* desc,
+ upb_sink *sink, int depth) {
+ upb_sink_startmsg(sink);
+
+ // Protect against cycles (possible because users may freely reassign message
+ // and repeated fields) by imposing a maximum recursion depth.
+ if (depth > UPB_SINK_MAX_NESTING) {
+ rb_raise(rb_eRuntimeError,
+ "Maximum recursion depth exceeded during encoding.");
+ }
+
+ MessageHeader* msg;
+ TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg);
+ void* msg_data = Message_data(msg);
+
+ upb_msg_iter i;
+ for (upb_msg_begin(&i, desc->msgdef);
+ !upb_msg_done(&i);
+ upb_msg_next(&i)) {
+ upb_fielddef *f = upb_msg_iter_field(&i);
+ uint32_t offset = desc->layout->offsets[upb_fielddef_index(f)];
+
+ if (upb_fielddef_isseq(f)) {
+ VALUE ary = DEREF(msg_data, offset, VALUE);
+ if (ary != Qnil) {
+ putary(ary, f, sink, depth);
+ }
+ } else if (upb_fielddef_isstring(f)) {
+ VALUE str = DEREF(msg_data, offset, VALUE);
+ if (RSTRING_LEN(str) > 0) {
+ putstr(str, f, sink);
+ }
+ } else if (upb_fielddef_issubmsg(f)) {
+ putsubmsg(DEREF(msg_data, offset, VALUE), f, sink, depth);
+ } else {
+ upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
+
+#define T(upbtypeconst, upbtype, ctype, default_value) \
+ case upbtypeconst: { \
+ ctype value = DEREF(msg_data, offset, ctype); \
+ if (value != default_value) { \
+ upb_sink_put##upbtype(sink, sel, value); \
+ } \
+ } \
+ break;
+
+ switch (upb_fielddef_type(f)) {
+ T(UPB_TYPE_FLOAT, float, float, 0.0)
+ T(UPB_TYPE_DOUBLE, double, double, 0.0)
+ T(UPB_TYPE_BOOL, bool, uint8_t, 0)
+ case UPB_TYPE_ENUM:
+ T(UPB_TYPE_INT32, int32, int32_t, 0)
+ T(UPB_TYPE_UINT32, uint32, uint32_t, 0)
+ T(UPB_TYPE_INT64, int64, int64_t, 0)
+ T(UPB_TYPE_UINT64, uint64, uint64_t, 0)
+
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE: rb_raise(rb_eRuntimeError, "Internal error.");
+ }
+
+#undef T
+
+ }
+ }
+
+ upb_status status;
+ upb_sink_endmsg(sink, &status);
+}
+
+static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
+ if (desc->pb_serialize_handlers == NULL) {
+ desc->pb_serialize_handlers =
+ upb_pb_encoder_newhandlers(desc->msgdef, &desc->pb_serialize_handlers);
+ }
+ return desc->pb_serialize_handlers;
+}
+
+static const upb_handlers* msgdef_json_serialize_handlers(Descriptor* desc) {
+ if (desc->json_serialize_handlers == NULL) {
+ desc->json_serialize_handlers =
+ upb_json_printer_newhandlers(
+ desc->msgdef, &desc->json_serialize_handlers);
+ }
+ return desc->json_serialize_handlers;
+}
+
+/*
+ * call-seq:
+ * MessageClass.encode(msg) => bytes
+ *
+ * Encodes the given message object to its serialized form in protocol buffers
+ * wire format.
+ */
+VALUE Message_encode(VALUE klass, VALUE msg_rb) {
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
+
+ stringsink sink;
+ stringsink_init(&sink);
+
+ const upb_handlers* serialize_handlers =
+ msgdef_pb_serialize_handlers(desc);
+
+ upb_pb_encoder encoder;
+ upb_pb_encoder_init(&encoder, serialize_handlers);
+ upb_pb_encoder_resetoutput(&encoder, &sink.sink);
+
+ putmsg(msg_rb, desc, upb_pb_encoder_input(&encoder), 0);
+
+ VALUE ret = rb_str_new(sink.ptr, sink.len);
+
+ upb_pb_encoder_uninit(&encoder);
+ stringsink_uninit(&sink);
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * MessageClass.encode_json(msg) => json_string
+ *
+ * Encodes the given message object into its serialized JSON representation.
+ */
+VALUE Message_encode_json(VALUE klass, VALUE msg_rb) {
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
+
+ stringsink sink;
+ stringsink_init(&sink);
+
+ const upb_handlers* serialize_handlers =
+ msgdef_json_serialize_handlers(desc);
+
+ upb_json_printer printer;
+ upb_json_printer_init(&printer, serialize_handlers);
+ upb_json_printer_resetoutput(&printer, &sink.sink);
+
+ putmsg(msg_rb, desc, upb_json_printer_input(&printer), 0);
+
+ VALUE ret = rb_str_new(sink.ptr, sink.len);
+
+ upb_json_printer_uninit(&printer);
+ stringsink_uninit(&sink);
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * Google::Protobuf.encode(msg) => bytes
+ *
+ * Encodes the given message object to protocol buffers wire format. This is an
+ * alternative to the #encode method on msg's class.
+ */
+VALUE Google_Protobuf_encode(VALUE self, VALUE msg_rb) {
+ VALUE klass = CLASS_OF(msg_rb);
+ return Message_encode(klass, msg_rb);
+}
+
+/*
+ * call-seq:
+ * Google::Protobuf.encode_json(msg) => json_string
+ *
+ * Encodes the given message object to its JSON representation. This is an
+ * alternative to the #encode_json method on msg's class.
+ */
+VALUE Google_Protobuf_encode_json(VALUE self, VALUE msg_rb) {
+ VALUE klass = CLASS_OF(msg_rb);
+ return Message_encode_json(klass, msg_rb);
+}
+
+/*
+ * call-seq:
+ * Google::Protobuf.decode(class, bytes) => msg
+ *
+ * Decodes the given bytes as protocol buffers wire format under the
+ * interpretation given by the given class's message definition. This is an
+ * alternative to the #decode method on the given class.
+ */
+VALUE Google_Protobuf_decode(VALUE self, VALUE klass, VALUE msg_rb) {
+ return Message_decode(klass, msg_rb);
+}
+
+/*
+ * call-seq:
+ * Google::Protobuf.decode_json(class, json_string) => msg
+ *
+ * Decodes the given JSON string under the interpretation given by the given
+ * class's message definition. This is an alternative to the #decode_json method
+ * on the given class.
+ */
+VALUE Google_Protobuf_decode_json(VALUE self, VALUE klass, VALUE msg_rb) {
+ return Message_decode_json(klass, msg_rb);
+}
diff --git a/ruby/ext/protobuf_c/extconf.rb b/ruby/ext/protobuf_c/extconf.rb
new file mode 100644
index 00000000..7f23b1a8
--- /dev/null
+++ b/ruby/ext/protobuf_c/extconf.rb
@@ -0,0 +1,23 @@
+#!/usr/bin/ruby
+
+require 'mkmf'
+
+upb_path = File.absolute_path(File.dirname($0)) + "/../../../upb"
+libs = ["upb_pic", "upb.pb_pic", "upb.json_pic"]
+system("cd #{upb_path}; make " + libs.map{|l| "lib/lib#{l}.a"}.join(" "))
+
+$CFLAGS += " -O3 -std=c99 -Wno-unused-function -DNDEBUG"
+
+find_header("upb/upb.h", upb_path) or
+ raise "Can't find upb headers"
+find_library("upb_pic", "upb_msgdef_new", upb_path + "/lib") or
+ raise "Can't find upb lib"
+find_library("upb.pb_pic", "upb_pbdecoder_init", upb_path + "/lib") or
+ raise "Can't find upb.pb lib"
+find_library("upb.json_pic", "upb_json_printer_init", upb_path + "/lib") or
+ raise "Can't find upb.pb lib"
+
+$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
+ "repeated_field.o", "encode_decode.o"]
+
+create_makefile("protobuf_c")
diff --git a/ruby/ext/protobuf_c/message.c b/ruby/ext/protobuf_c/message.c
new file mode 100644
index 00000000..105b7807
--- /dev/null
+++ b/ruby/ext/protobuf_c/message.c
@@ -0,0 +1,463 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Class/module creation from msgdefs and enumdefs, respectively.
+// -----------------------------------------------------------------------------
+
+void* Message_data(void* msg) {
+ return ((uint8_t *)msg) + sizeof(MessageHeader);
+}
+
+void Message_mark(void* _self) {
+ MessageHeader* self = (MessageHeader *)_self;
+ layout_mark(self->descriptor->layout, Message_data(self));
+}
+
+void Message_free(void* self) {
+ xfree(self);
+}
+
+rb_data_type_t Message_type = {
+ "Message",
+ { Message_mark, Message_free, NULL },
+};
+
+VALUE Message_alloc(VALUE klass) {
+ VALUE descriptor = rb_iv_get(klass, kDescriptorInstanceVar);
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
+ MessageHeader* msg = (MessageHeader*)ALLOC_N(
+ uint8_t, sizeof(MessageHeader) + desc->layout->size);
+ memset(Message_data(msg), 0, desc->layout->size);
+
+ // We wrap first so that everything in the message object is GC-rooted in case
+ // a collection happens during object creation in layout_init().
+ VALUE ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
+ msg->descriptor = desc;
+ rb_iv_set(ret, kDescriptorInstanceVar, descriptor);
+
+ layout_init(desc->layout, Message_data(msg));
+
+ return ret;
+}
+
+/*
+ * call-seq:
+ * Message.method_missing(*args)
+ *
+ * Provides accessors and setters for message fields according to their field
+ * names. For any field whose name does not conflict with a built-in method, an
+ * accessor is provided with the same name as the field, and a setter is
+ * provided with the name of the field plus the '=' suffix. Thus, given a
+ * message instance 'msg' with field 'foo', the following code is valid:
+ *
+ * msg.foo = 42
+ * puts msg.foo
+ */
+VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "Expected method name as first argument.");
+ }
+ VALUE method_name = argv[0];
+ if (!SYMBOL_P(method_name)) {
+ rb_raise(rb_eArgError, "Expected symbol as method name.");
+ }
+ VALUE method_str = rb_id2str(SYM2ID(method_name));
+ char* name = RSTRING_PTR(method_str);
+ size_t name_len = RSTRING_LEN(method_str);
+ bool setter = false;
+
+ // Setters have names that end in '='.
+ if (name[name_len - 1] == '=') {
+ setter = true;
+ name_len--;
+ }
+
+ const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
+ name, name_len);
+
+ if (f == NULL) {
+ rb_raise(rb_eArgError, "Unknown field");
+ }
+
+ if (setter) {
+ if (argc < 2) {
+ rb_raise(rb_eArgError, "No value provided to setter.");
+ }
+ layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
+ return Qnil;
+ } else {
+ return layout_get(self->descriptor->layout, Message_data(self), f);
+ }
+}
+
+int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ if (!SYMBOL_P(key)) {
+ rb_raise(rb_eArgError,
+ "Expected symbols as hash keys in initialization map.");
+ }
+
+ VALUE method_str = rb_id2str(SYM2ID(key));
+ char* name = RSTRING_PTR(method_str);
+ const upb_fielddef* f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
+ if (f == NULL) {
+ rb_raise(rb_eArgError,
+ "Unknown field name in initialization map entry.");
+ }
+
+ if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
+ if (TYPE(val) != T_ARRAY) {
+ rb_raise(rb_eArgError,
+ "Expected array as initializer value for repeated field.");
+ }
+ VALUE ary = layout_get(self->descriptor->layout, Message_data(self), f);
+ for (int i = 0; i < RARRAY_LEN(val); i++) {
+ RepeatedField_push(ary, rb_ary_entry(val, i));
+ }
+ } else {
+ layout_set(self->descriptor->layout, Message_data(self), f, val);
+ }
+ return 0;
+}
+
+/*
+ * call-seq:
+ * Message.new(kwargs) => new_message
+ *
+ * Creates a new instance of the given message class. Keyword arguments may be
+ * provided with keywords corresponding to field names.
+ *
+ * Note that no literal Message class exists. Only concrete classes per message
+ * type exist, as provided by the #msgclass method on Descriptors after they
+ * have been added to a pool. The method definitions described here on the
+ * Message class are provided on each concrete message class.
+ */
+VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
+ if (argc == 0) {
+ return Qnil;
+ }
+ if (argc != 1) {
+ rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
+ }
+ VALUE hash_args = argv[0];
+ if (TYPE(hash_args) != T_HASH) {
+ rb_raise(rb_eArgError, "Expected hash arguments.");
+ }
+
+ rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Message.dup => new_message
+ *
+ * Performs a shallow copy of this message and returns the new copy.
+ */
+VALUE Message_dup(VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+ MessageHeader* new_msg_self;
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+
+ layout_dup(self->descriptor->layout,
+ Message_data(new_msg_self),
+ Message_data(self));
+
+ return new_msg;
+}
+
+// Internal only; used by Google::Protobuf.deep_copy.
+VALUE Message_deep_copy(VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
+ MessageHeader* new_msg_self;
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
+
+ layout_deep_copy(self->descriptor->layout,
+ Message_data(new_msg_self),
+ Message_data(self));
+
+ return new_msg;
+}
+
+/*
+ * call-seq:
+ * Message.==(other) => boolean
+ *
+ * Performs a deep comparison of this message with another. Messages are equal
+ * if they have the same type and if each field is equal according to the :==
+ * method's semantics (a more efficient comparison may actually be done if the
+ * field is of a primitive type).
+ */
+VALUE Message_eq(VALUE _self, VALUE _other) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ MessageHeader* other;
+ TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
+
+ if (self->descriptor != other->descriptor) {
+ return Qfalse;
+ }
+
+ return layout_eq(self->descriptor->layout,
+ Message_data(self),
+ Message_data(other));
+}
+
+/*
+ * call-seq:
+ * Message.hash => hash_value
+ *
+ * Returns a hash value that represents this message's field values.
+ */
+VALUE Message_hash(VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ return layout_hash(self->descriptor->layout, Message_data(self));
+}
+
+/*
+ * call-seq:
+ * Message.inspect => string
+ *
+ * Returns a human-readable string representing this message. It will be
+ * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
+ * field's value is represented according to its own #inspect method.
+ */
+VALUE Message_inspect(VALUE _self) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+
+ VALUE str = rb_str_new2("<");
+ str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
+ str = rb_str_cat2(str, ": ");
+ str = rb_str_append(str, layout_inspect(
+ self->descriptor->layout, Message_data(self)));
+ str = rb_str_cat2(str, ">");
+ return str;
+}
+
+/*
+ * call-seq:
+ * Message.[](index) => value
+ *
+ * Accesses a field's value by field name. The provided field name should be a
+ * string.
+ */
+VALUE Message_index(VALUE _self, VALUE field_name) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+ Check_Type(field_name, T_STRING);
+ const upb_fielddef* field =
+ upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+ if (field == NULL) {
+ return Qnil;
+ }
+ return layout_get(self->descriptor->layout, Message_data(self), field);
+}
+
+/*
+ * call-seq:
+ * Message.[]=(index, value)
+ *
+ * Sets a field's value by field name. The provided field name should be a
+ * string.
+ */
+VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
+ MessageHeader* self;
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
+ Check_Type(field_name, T_STRING);
+ const upb_fielddef* field =
+ upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
+ if (field == NULL) {
+ rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
+ }
+ layout_set(self->descriptor->layout, Message_data(self), field, value);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * Message.descriptor => descriptor
+ *
+ * Class method that returns the Descriptor instance corresponding to this
+ * message class's type.
+ */
+VALUE Message_descriptor(VALUE klass) {
+ return rb_iv_get(klass, kDescriptorInstanceVar);
+}
+
+VALUE build_class_from_descriptor(Descriptor* desc) {
+ if (desc->layout == NULL) {
+ desc->layout = create_layout(desc->msgdef);
+ }
+ if (desc->fill_method == NULL) {
+ desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
+ }
+
+ const char* name = upb_msgdef_fullname(desc->msgdef);
+ if (name == NULL) {
+ rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
+ }
+
+ VALUE klass = rb_define_class_id(
+ // Docs say this parameter is ignored. User will assign return value to
+ // their own toplevel constant class name.
+ rb_intern("Message"),
+ rb_cObject);
+ rb_iv_set(klass, kDescriptorInstanceVar, get_def_obj(desc->msgdef));
+ rb_define_alloc_func(klass, Message_alloc);
+ rb_define_method(klass, "method_missing",
+ Message_method_missing, -1);
+ rb_define_method(klass, "initialize", Message_initialize, -1);
+ rb_define_method(klass, "dup", Message_dup, 0);
+ // Also define #clone so that we don't inherit Object#clone.
+ rb_define_method(klass, "clone", Message_dup, 0);
+ rb_define_method(klass, "==", Message_eq, 1);
+ rb_define_method(klass, "hash", Message_hash, 0);
+ rb_define_method(klass, "inspect", Message_inspect, 0);
+ rb_define_method(klass, "[]", Message_index, 1);
+ rb_define_method(klass, "[]=", Message_index_set, 2);
+ rb_define_singleton_method(klass, "decode", Message_decode, 1);
+ rb_define_singleton_method(klass, "encode", Message_encode, 1);
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
+ rb_define_singleton_method(klass, "encode_json", Message_encode_json, 1);
+ rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
+ return klass;
+}
+
+/*
+ * call-seq:
+ * Enum.lookup(number) => name
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by number and returns its name as a Ruby symbol, or nil if not found.
+ */
+VALUE enum_lookup(VALUE self, VALUE number) {
+ int32_t num = NUM2INT(number);
+ VALUE desc = rb_iv_get(self, kDescriptorInstanceVar);
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+
+ const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
+ if (name == NULL) {
+ return Qnil;
+ } else {
+ return ID2SYM(rb_intern(name));
+ }
+}
+
+/*
+ * call-seq:
+ * Enum.resolve(name) => number
+ *
+ * This module method, provided on each generated enum module, looks up an enum
+ * value by name (as a Ruby symbol) and returns its name, or nil if not found.
+ */
+VALUE enum_resolve(VALUE self, VALUE sym) {
+ const char* name = rb_id2name(SYM2ID(sym));
+ VALUE desc = rb_iv_get(self, kDescriptorInstanceVar);
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
+
+ int32_t num = 0;
+ bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
+ if (!found) {
+ return Qnil;
+ } else {
+ return INT2NUM(num);
+ }
+}
+
+/*
+ * call-seq:
+ * Enum.descriptor
+ *
+ * This module method, provided on each generated enum module, returns the
+ * EnumDescriptor corresponding to this enum type.
+ */
+VALUE enum_descriptor(VALUE self) {
+ return rb_iv_get(self, kDescriptorInstanceVar);
+}
+
+VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
+ VALUE mod = rb_define_module_id(
+ rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
+
+ upb_enum_iter it;
+ for (upb_enum_begin(&it, enumdesc->enumdef);
+ !upb_enum_done(&it);
+ upb_enum_next(&it)) {
+ const char* name = upb_enum_iter_name(&it);
+ int32_t value = upb_enum_iter_number(&it);
+ if (name[0] < 'A' || name[0] > 'Z') {
+ rb_raise(rb_eTypeError,
+ "Enum value '%s' does not start with an uppercase letter "
+ "as is required for Ruby constants.",
+ name);
+ }
+ rb_define_const(mod, name, INT2NUM(value));
+ }
+
+ rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
+ rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
+ rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
+ rb_iv_set(mod, kDescriptorInstanceVar, get_def_obj(enumdesc->enumdef));
+
+ return mod;
+}
+
+/*
+ * call-seq:
+ * Google::Protobuf.deep_copy(obj) => copy_of_obj
+ *
+ * Performs a deep copy of either a RepeatedField instance or a message object,
+ * recursively copying its members.
+ */
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
+ VALUE klass = CLASS_OF(obj);
+ if (klass == cRepeatedField) {
+ return RepeatedField_deep_copy(obj);
+ } else {
+ return Message_deep_copy(obj);
+ }
+}
diff --git a/ruby/ext/protobuf_c/protobuf.c b/ruby/ext/protobuf_c/protobuf.c
new file mode 100644
index 00000000..d5862284
--- /dev/null
+++ b/ruby/ext/protobuf_c/protobuf.c
@@ -0,0 +1,102 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+
+// This is a hash table from def objects (encoded by converting pointers to
+// Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
+VALUE upb_def_to_ruby_obj_map;
+
+void add_def_obj(const void* def, VALUE value) {
+ rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
+}
+
+VALUE get_def_obj(const void* def) {
+ return rb_hash_aref(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def));
+}
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+// Raises a Ruby error if |status| is not OK, using its error message.
+void check_upb_status(const upb_status* status, const char* msg) {
+ if (!upb_ok(status)) {
+ rb_raise(rb_eRuntimeError, "%s: %s\n", msg, upb_status_errmsg(status));
+ }
+}
+
+// String encodings: we look these up once, at load time, and then cache them
+// here.
+rb_encoding* kRubyStringUtf8Encoding;
+rb_encoding* kRubyStringASCIIEncoding;
+rb_encoding* kRubyString8bitEncoding;
+
+// -----------------------------------------------------------------------------
+// Initialization/entry point.
+// -----------------------------------------------------------------------------
+
+// This must be named "Init_protobuf_c" because the Ruby module is named
+// "protobuf_c" -- the VM looks for this symbol in our .so.
+void Init_protobuf_c() {
+ VALUE google = rb_define_module("Google");
+ VALUE protobuf = rb_define_module_under(google, "Protobuf");
+ VALUE internal = rb_define_module_under(protobuf, "Internal");
+ DescriptorPool_register(protobuf);
+ Descriptor_register(protobuf);
+ FieldDescriptor_register(protobuf);
+ EnumDescriptor_register(protobuf);
+ MessageBuilderContext_register(internal);
+ EnumBuilderContext_register(internal);
+ Builder_register(internal);
+ RepeatedField_register(protobuf);
+
+ rb_define_singleton_method(protobuf, "encode", Google_Protobuf_encode, 1);
+ rb_define_singleton_method(protobuf, "decode", Google_Protobuf_decode, 2);
+ rb_define_singleton_method(protobuf, "encode_json",
+ Google_Protobuf_encode_json, 1);
+ rb_define_singleton_method(protobuf, "decode_json",
+ Google_Protobuf_decode_json, 2);
+
+ rb_define_singleton_method(protobuf, "deep_copy",
+ Google_Protobuf_deep_copy, 1);
+
+ kRubyStringUtf8Encoding = rb_utf8_encoding();
+ kRubyStringASCIIEncoding = rb_usascii_encoding();
+ kRubyString8bitEncoding = rb_ascii8bit_encoding();
+
+ upb_def_to_ruby_obj_map = rb_hash_new();
+ rb_gc_register_address(&upb_def_to_ruby_obj_map);
+}
diff --git a/ruby/ext/protobuf_c/protobuf.h b/ruby/ext/protobuf_c/protobuf.h
new file mode 100644
index 00000000..a7f6f539
--- /dev/null
+++ b/ruby/ext/protobuf_c/protobuf.h
@@ -0,0 +1,404 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
+#define __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
+
+#include <ruby/ruby.h>
+#include <ruby/vm.h>
+#include <ruby/encoding.h>
+
+#include "upb/def.h"
+#include "upb/handlers.h"
+#include "upb/pb/decoder.h"
+#include "upb/pb/encoder.h"
+#include "upb/pb/glue.h"
+#include "upb/json/parser.h"
+#include "upb/json/printer.h"
+#include "upb/shim/shim.h"
+#include "upb/symtab.h"
+
+// Forward decls.
+struct DescriptorPool;
+struct Descriptor;
+struct FieldDescriptor;
+struct EnumDescriptor;
+struct MessageLayout;
+struct MessageHeader;
+struct MessageBuilderContext;
+struct EnumBuilderContext;
+struct Builder;
+
+typedef struct DescriptorPool DescriptorPool;
+typedef struct Descriptor Descriptor;
+typedef struct FieldDescriptor FieldDescriptor;
+typedef struct EnumDescriptor EnumDescriptor;
+typedef struct MessageLayout MessageLayout;
+typedef struct MessageHeader MessageHeader;
+typedef struct MessageBuilderContext MessageBuilderContext;
+typedef struct EnumBuilderContext EnumBuilderContext;
+typedef struct Builder Builder;
+
+/*
+ It can be a bit confusing how the C structs defined below and the Ruby
+ objects interact and hold references to each other. First, a few principles:
+
+ - Ruby's "TypedData" abstraction lets a Ruby VALUE hold a pointer to a C
+ struct (or arbitrary memory chunk), own it, and free it when collected.
+ Thus, each struct below will have a corresponding Ruby object
+ wrapping/owning it.
+
+ - To get back from an underlying upb {msg,enum}def to the Ruby object, we
+ keep a global hashmap, accessed by get_def_obj/add_def_obj below.
+
+ The in-memory structure is then something like:
+
+ Ruby | upb
+ |
+ DescriptorPool ------------|-----------> upb_symtab____________________
+ | | (message types) \
+ | v \
+ Descriptor ---------------|-----------> upb_msgdef (enum types)|
+ |--> msgclass | | ^ |
+ | (dynamically built) | | | (submsg fields) |
+ |--> MessageLayout | | | /
+ |--------------------------|> decoder method| | /
+ \--------------------------|> serialize | | /
+ | handlers v | /
+ FieldDescriptor -----------|-----------> upb_fielddef /
+ | | /
+ | v (enum fields) /
+ EnumDescriptor ------------|-----------> upb_enumdef <----------'
+ |
+ |
+ ^ | \___/
+ `---------------|-----------------' (get_def_obj map)
+ */
+
+// -----------------------------------------------------------------------------
+// Ruby class structure definitions.
+// -----------------------------------------------------------------------------
+
+struct DescriptorPool {
+ upb_symtab* symtab;
+};
+
+struct Descriptor {
+ const upb_msgdef* msgdef;
+ MessageLayout* layout;
+ VALUE klass; // begins as nil
+ const upb_handlers* fill_handlers;
+ const upb_pbdecodermethod* fill_method;
+ const upb_handlers* pb_serialize_handlers;
+ const upb_handlers* json_serialize_handlers;
+};
+
+struct FieldDescriptor {
+ const upb_fielddef* fielddef;
+};
+
+struct EnumDescriptor {
+ const upb_enumdef* enumdef;
+ VALUE module; // begins as nil
+};
+
+struct MessageBuilderContext {
+ VALUE descriptor;
+};
+
+struct EnumBuilderContext {
+ VALUE enumdesc;
+};
+
+struct Builder {
+ VALUE pending_list;
+ upb_def** defs; // used only while finalizing
+};
+
+extern VALUE cDescriptorPool;
+extern VALUE cDescriptor;
+extern VALUE cFieldDescriptor;
+extern VALUE cEnumDescriptor;
+extern VALUE cMessageBuilderContext;
+extern VALUE cEnumBuilderContext;
+extern VALUE cBuilder;
+
+extern const char* kDescriptorInstanceVar;
+
+// We forward-declare all of the Ruby method implementations here because we
+// sometimes call the methods directly across .c files, rather than going
+// through Ruby's method dispatching (e.g. during message parse). It's cleaner
+// to keep the list of object methods together than to split them between
+// static-in-file definitions and header declarations.
+
+void DescriptorPool_mark(void* _self);
+void DescriptorPool_free(void* _self);
+VALUE DescriptorPool_alloc(VALUE klass);
+void DescriptorPool_register(VALUE module);
+DescriptorPool* ruby_to_DescriptorPool(VALUE value);
+VALUE DescriptorPool_add(VALUE _self, VALUE def);
+VALUE DescriptorPool_build(VALUE _self);
+VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
+VALUE DescriptorPool_generated_pool(VALUE _self);
+
+void Descriptor_mark(void* _self);
+void Descriptor_free(void* _self);
+VALUE Descriptor_alloc(VALUE klass);
+void Descriptor_register(VALUE module);
+Descriptor* ruby_to_Descriptor(VALUE value);
+VALUE Descriptor_name(VALUE _self);
+VALUE Descriptor_name_set(VALUE _self, VALUE str);
+VALUE Descriptor_each(VALUE _self);
+VALUE Descriptor_lookup(VALUE _self, VALUE name);
+VALUE Descriptor_add_field(VALUE _self, VALUE obj);
+VALUE Descriptor_msgclass(VALUE _self);
+extern const rb_data_type_t _Descriptor_type;
+
+void FieldDescriptor_mark(void* _self);
+void FieldDescriptor_free(void* _self);
+VALUE FieldDescriptor_alloc(VALUE klass);
+void FieldDescriptor_register(VALUE module);
+FieldDescriptor* ruby_to_FieldDescriptor(VALUE value);
+VALUE FieldDescriptor_name(VALUE _self);
+VALUE FieldDescriptor_name_set(VALUE _self, VALUE str);
+VALUE FieldDescriptor_type(VALUE _self);
+VALUE FieldDescriptor_type_set(VALUE _self, VALUE type);
+VALUE FieldDescriptor_label(VALUE _self);
+VALUE FieldDescriptor_label_set(VALUE _self, VALUE label);
+VALUE FieldDescriptor_number(VALUE _self);
+VALUE FieldDescriptor_number_set(VALUE _self, VALUE number);
+VALUE FieldDescriptor_submsg_name(VALUE _self);
+VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value);
+VALUE FieldDescriptor_subtype(VALUE _self);
+VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
+VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
+upb_fieldtype_t ruby_to_fieldtype(VALUE type);
+VALUE fieldtype_to_ruby(upb_fieldtype_t type);
+
+void EnumDescriptor_mark(void* _self);
+void EnumDescriptor_free(void* _self);
+VALUE EnumDescriptor_alloc(VALUE klass);
+void EnumDescriptor_register(VALUE module);
+EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
+VALUE EnumDescriptor_name(VALUE _self);
+VALUE EnumDescriptor_name_set(VALUE _self, VALUE str);
+VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number);
+VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name);
+VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number);
+VALUE EnumDescriptor_each(VALUE _self);
+VALUE EnumDescriptor_enummodule(VALUE _self);
+extern const rb_data_type_t _EnumDescriptor_type;
+
+void MessageBuilderContext_mark(void* _self);
+void MessageBuilderContext_free(void* _self);
+VALUE MessageBuilderContext_alloc(VALUE klass);
+void MessageBuilderContext_register(VALUE module);
+MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
+VALUE MessageBuilderContext_initialize(VALUE _self, VALUE descriptor);
+VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
+VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
+
+void EnumBuilderContext_mark(void* _self);
+void EnumBuilderContext_free(void* _self);
+VALUE EnumBuilderContext_alloc(VALUE klass);
+void EnumBuilderContext_register(VALUE module);
+EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
+VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc);
+VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
+
+void Builder_mark(void* _self);
+void Builder_free(void* _self);
+VALUE Builder_alloc(VALUE klass);
+void Builder_register(VALUE module);
+Builder* ruby_to_Builder(VALUE value);
+VALUE Builder_add_message(VALUE _self, VALUE name);
+VALUE Builder_add_enum(VALUE _self, VALUE name);
+VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
+
+// -----------------------------------------------------------------------------
+// Native slot storage abstraction.
+// -----------------------------------------------------------------------------
+
+size_t native_slot_size(upb_fieldtype_t type);
+void native_slot_set(upb_fieldtype_t type,
+ VALUE type_class,
+ void* memory,
+ VALUE value);
+VALUE native_slot_get(upb_fieldtype_t type,
+ VALUE type_class,
+ void* memory);
+void native_slot_init(upb_fieldtype_t type, void* memory);
+void native_slot_mark(upb_fieldtype_t type, void* memory);
+void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
+void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
+bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
+
+void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value);
+
+extern rb_encoding* kRubyStringUtf8Encoding;
+extern rb_encoding* kRubyStringASCIIEncoding;
+extern rb_encoding* kRubyString8bitEncoding;
+
+// -----------------------------------------------------------------------------
+// Repeated field container type.
+// -----------------------------------------------------------------------------
+
+typedef struct {
+ upb_fieldtype_t field_type;
+ VALUE field_type_class;
+ void* elements;
+ int size;
+ int capacity;
+} RepeatedField;
+
+void RepeatedField_mark(void* self);
+void RepeatedField_free(void* self);
+VALUE RepeatedField_alloc(VALUE klass);
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self);
+void RepeatedField_register(VALUE module);
+
+extern const rb_data_type_t RepeatedField_type;
+extern VALUE cRepeatedField;
+
+RepeatedField* ruby_to_RepeatedField(VALUE value);
+
+void RepeatedField_register(VALUE module);
+VALUE RepeatedField_each(VALUE _self);
+VALUE RepeatedField_index(VALUE _self, VALUE _index);
+void* RepeatedField_index_native(VALUE _self, int index);
+VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val);
+void RepeatedField_reserve(RepeatedField* self, int new_size);
+VALUE RepeatedField_push(VALUE _self, VALUE val);
+void RepeatedField_push_native(VALUE _self, void* data);
+VALUE RepeatedField_pop(VALUE _self);
+VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self);
+VALUE RepeatedField_replace(VALUE _self, VALUE list);
+VALUE RepeatedField_clear(VALUE _self);
+VALUE RepeatedField_length(VALUE _self);
+VALUE RepeatedField_dup(VALUE _self);
+VALUE RepeatedField_deep_copy(VALUE _self);
+VALUE RepeatedField_eq(VALUE _self, VALUE _other);
+VALUE RepeatedField_hash(VALUE _self);
+VALUE RepeatedField_inspect(VALUE _self);
+VALUE RepeatedField_plus(VALUE _self, VALUE list);
+
+// -----------------------------------------------------------------------------
+// Message layout / storage.
+// -----------------------------------------------------------------------------
+
+struct MessageLayout {
+ const upb_msgdef* msgdef;
+ size_t* offsets;
+ size_t size;
+};
+
+MessageLayout* create_layout(const upb_msgdef* msgdef);
+void free_layout(MessageLayout* layout);
+VALUE layout_get(MessageLayout* layout,
+ void* storage,
+ const upb_fielddef* field);
+void layout_set(MessageLayout* layout,
+ void* storage,
+ const upb_fielddef* field,
+ VALUE val);
+void layout_init(MessageLayout* layout, void* storage);
+void layout_mark(MessageLayout* layout, void* storage);
+void layout_dup(MessageLayout* layout, void* to, void* from);
+void layout_deep_copy(MessageLayout* layout, void* to, void* from);
+VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2);
+VALUE layout_hash(MessageLayout* layout, void* storage);
+VALUE layout_inspect(MessageLayout* layout, void* storage);
+
+// -----------------------------------------------------------------------------
+// Message class creation.
+// -----------------------------------------------------------------------------
+
+struct MessageHeader {
+ Descriptor* descriptor; // kept alive by self.class.descriptor reference.
+ // Data comes after this.
+};
+
+extern rb_data_type_t Message_type;
+
+VALUE build_class_from_descriptor(Descriptor* descriptor);
+void* Message_data(void* msg);
+void Message_mark(void* self);
+void Message_free(void* self);
+VALUE Message_alloc(VALUE klass);
+VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self);
+VALUE Message_initialize(int argc, VALUE* argv, VALUE _self);
+VALUE Message_dup(VALUE _self);
+VALUE Message_deep_copy(VALUE _self);
+VALUE Message_eq(VALUE _self, VALUE _other);
+VALUE Message_hash(VALUE _self);
+VALUE Message_inspect(VALUE _self);
+VALUE Message_index(VALUE _self, VALUE field_name);
+VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
+VALUE Message_descriptor(VALUE klass);
+VALUE Message_decode(VALUE klass, VALUE data);
+VALUE Message_encode(VALUE klass, VALUE msg_rb);
+VALUE Message_decode_json(VALUE klass, VALUE data);
+VALUE Message_encode_json(VALUE klass, VALUE msg_rb);
+
+VALUE Google_Protobuf_encode(VALUE self, VALUE msg_rb);
+VALUE Google_Protobuf_decode(VALUE self, VALUE klass, VALUE msg_rb);
+VALUE Google_Protobuf_encode_json(VALUE self, VALUE msg_rb);
+VALUE Google_Protobuf_decode_json(VALUE self, VALUE klass, VALUE msg_rb);
+
+VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
+
+VALUE build_module_from_enumdesc(EnumDescriptor* enumdef);
+VALUE enum_lookup(VALUE self, VALUE number);
+VALUE enum_resolve(VALUE self, VALUE sym);
+
+const upb_pbdecodermethod *new_fillmsg_decodermethod(
+ Descriptor* descriptor, const void *owner);
+
+// -----------------------------------------------------------------------------
+// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
+// instances.
+// -----------------------------------------------------------------------------
+void add_def_obj(const void* def, VALUE value);
+VALUE get_def_obj(const void* def);
+
+// -----------------------------------------------------------------------------
+// Utilities.
+// -----------------------------------------------------------------------------
+
+void check_upb_status(const upb_status* status, const char* msg);
+
+#define CHECK_UPB(code, msg) do { \
+ upb_status status = UPB_STATUS_INIT; \
+ code; \
+ check_upb_status(&status, msg); \
+} while (0)
+
+#endif // __GOOGLE_PROTOBUF_RUBY_PROTOBUF_H__
diff --git a/ruby/ext/protobuf_c/repeated_field.c b/ruby/ext/protobuf_c/repeated_field.c
new file mode 100644
index 00000000..6bd13b07
--- /dev/null
+++ b/ruby/ext/protobuf_c/repeated_field.c
@@ -0,0 +1,597 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+// -----------------------------------------------------------------------------
+// Repeated field container type.
+// -----------------------------------------------------------------------------
+
+const rb_data_type_t RepeatedField_type = {
+ "Google::Protobuf::RepeatedField",
+ { RepeatedField_mark, RepeatedField_free, NULL },
+};
+
+VALUE cRepeatedField;
+
+RepeatedField* ruby_to_RepeatedField(VALUE _self) {
+ RepeatedField* self;
+ TypedData_Get_Struct(_self, RepeatedField, &RepeatedField_type, self);
+ return self;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.each(&block)
+ *
+ * Invokes the block once for each element of the repeated field. RepeatedField
+ * also includes Enumerable; combined with this method, the repeated field thus
+ * acts like an ordinary Ruby sequence.
+ */
+VALUE RepeatedField_each(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+ int element_size = native_slot_size(field_type);
+
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += element_size) {
+ void* memory = (void *) (((uint8_t *)self->elements) + off);
+ VALUE val = native_slot_get(field_type, field_type_class, memory);
+ rb_yield(val);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.[](index) => value
+ *
+ * Accesses the element at the given index. Throws an exception on out-of-bounds
+ * errors.
+ */
+VALUE RepeatedField_index(VALUE _self, VALUE _index) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ int element_size = native_slot_size(self->field_type);
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+
+ int index = NUM2INT(_index);
+ if (index < 0 || index >= self->size) {
+ rb_raise(rb_eRangeError, "Index out of range");
+ }
+
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
+ return native_slot_get(field_type, field_type_class, memory);
+}
+
+/*
+ * call-seq:
+ * RepeatedField.[]=(index, value)
+ *
+ * Sets the element at the given index. On out-of-bounds assignments, extends
+ * the array and fills the hole (if any) with default values.
+ */
+VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+ int element_size = native_slot_size(field_type);
+
+ int index = NUM2INT(_index);
+ if (index < 0 || index >= (INT_MAX - 1)) {
+ rb_raise(rb_eRangeError, "Index out of range");
+ }
+ if (index >= self->size) {
+ RepeatedField_reserve(self, index + 1);
+ upb_fieldtype_t field_type = self->field_type;
+ int element_size = native_slot_size(field_type);
+ for (int i = self->size; i <= index; i++) {
+ void* elem = (void *)(((uint8_t *)self->elements) + i * element_size);
+ native_slot_init(field_type, elem);
+ }
+ self->size = index + 1;
+ }
+
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
+ native_slot_set(field_type, field_type_class, memory, val);
+ return Qnil;
+}
+
+static int kInitialSize = 8;
+
+void RepeatedField_reserve(RepeatedField* self, int new_size) {
+ if (new_size <= self->capacity) {
+ return;
+ }
+ if (self->capacity == 0) {
+ self->capacity = kInitialSize;
+ }
+ while (self->capacity < new_size) {
+ self->capacity *= 2;
+ }
+ void* old_elems = self->elements;
+ int elem_size = native_slot_size(self->field_type);
+ self->elements = ALLOC_N(uint8_t, elem_size * self->capacity);
+ if (old_elems != NULL) {
+ memcpy(self->elements, old_elems, self->size * elem_size);
+ xfree(old_elems);
+ }
+}
+
+/*
+ * call-seq:
+ * RepeatedField.push(value)
+ *
+ * Adds a new element to the repeated field.
+ */
+VALUE RepeatedField_push(VALUE _self, VALUE val) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ int element_size = native_slot_size(field_type);
+ RepeatedField_reserve(self, self->size + 1);
+ int index = self->size;
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
+ native_slot_set(field_type, self->field_type_class, memory, val);
+ // native_slot_set may raise an error; bump index only after set.
+ self->size++;
+ return _self;
+}
+
+// Used by parsing handlers.
+void RepeatedField_push_native(VALUE _self, void* data) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ int element_size = native_slot_size(field_type);
+ RepeatedField_reserve(self, self->size + 1);
+ int index = self->size;
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
+ memcpy(memory, data, element_size);
+ self->size++;
+}
+
+void* RepeatedField_index_native(VALUE _self, int index) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ int element_size = native_slot_size(field_type);
+ return ((uint8_t *)self->elements) + index * element_size;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.pop => value
+ *
+ * Removes the last element and returns it. Throws an exception if the repeated
+ * field is empty.
+ */
+VALUE RepeatedField_pop(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+ int element_size = native_slot_size(field_type);
+ if (self->size == 0) {
+ rb_raise(rb_eRangeError, "Pop from empty repeated field is not allowed.");
+ }
+ int index = self->size - 1;
+ void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
+ VALUE ret = native_slot_get(field_type, field_type_class, memory);
+ self->size--;
+ return ret;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.insert(*args)
+ *
+ * Pushes each arg in turn onto the end of the repeated field.
+ */
+VALUE RepeatedField_insert(int argc, VALUE* argv, VALUE _self) {
+ for (int i = 0; i < argc; i++) {
+ RepeatedField_push(_self, argv[i]);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.replace(list)
+ *
+ * Replaces the contents of the repeated field with the given list of elements.
+ */
+VALUE RepeatedField_replace(VALUE _self, VALUE list) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ Check_Type(list, T_ARRAY);
+ self->size = 0;
+ for (int i = 0; i < RARRAY_LEN(list); i++) {
+ RepeatedField_push(_self, rb_ary_entry(list, i));
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.clear
+ *
+ * Clears (removes all elements from) this repeated field.
+ */
+VALUE RepeatedField_clear(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ self->size = 0;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.length
+ *
+ * Returns the length of this repeated field.
+ */
+VALUE RepeatedField_length(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ return INT2NUM(self->size);
+}
+
+static VALUE RepeatedField_new_this_type(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ VALUE new_rptfield = Qnil;
+ VALUE element_type = fieldtype_to_ruby(self->field_type);
+ if (self->field_type_class != Qnil) {
+ new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
+ element_type, self->field_type_class);
+ } else {
+ new_rptfield = rb_funcall(CLASS_OF(_self), rb_intern("new"), 1,
+ element_type);
+ }
+ return new_rptfield;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.dup => repeated_field
+ *
+ * Duplicates this repeated field with a shallow copy. References to all
+ * non-primitive element objects (e.g., submessages) are shared.
+ */
+VALUE RepeatedField_dup(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
+ RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
+ RepeatedField_reserve(new_rptfield_self, self->size);
+ upb_fieldtype_t field_type = self->field_type;
+ size_t elem_size = native_slot_size(field_type);
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += elem_size) {
+ void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
+ void* from_mem = (uint8_t *)self->elements + off;
+ native_slot_dup(field_type, to_mem, from_mem);
+ new_rptfield_self->size++;
+ }
+
+ return new_rptfield;
+}
+
+// Internal only: used by Google::Protobuf.deep_copy.
+VALUE RepeatedField_deep_copy(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
+ RepeatedField* new_rptfield_self = ruby_to_RepeatedField(new_rptfield);
+ RepeatedField_reserve(new_rptfield_self, self->size);
+ upb_fieldtype_t field_type = self->field_type;
+ size_t elem_size = native_slot_size(field_type);
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += elem_size) {
+ void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
+ void* from_mem = (uint8_t *)self->elements + off;
+ native_slot_deep_copy(field_type, to_mem, from_mem);
+ new_rptfield_self->size++;
+ }
+
+ return new_rptfield;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.==(other) => boolean
+ *
+ * Compares this repeated field to another. Repeated fields are equal if their
+ * element types are equal, their lengths are equal, and each element is equal.
+ * Elements are compared as per normal Ruby semantics, by calling their :==
+ * methods (or performing a more efficient comparison for primitive types).
+ */
+VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
+ if (_self == _other) {
+ return Qtrue;
+ }
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+
+ // Inefficient but workable: to support comparison to a generic array, we
+ // build a temporary RepeatedField of our type.
+ if (TYPE(_other) == T_ARRAY) {
+ VALUE new_rptfield = RepeatedField_new_this_type(_self);
+ for (int i = 0; i < RARRAY_LEN(_other); i++) {
+ VALUE elem = rb_ary_entry(_other, i);
+ RepeatedField_push(new_rptfield, elem);
+ }
+ _other = new_rptfield;
+ }
+
+ RepeatedField* other = ruby_to_RepeatedField(_other);
+ if (self->field_type != other->field_type ||
+ self->field_type_class != other->field_type_class ||
+ self->size != other->size) {
+ return Qfalse;
+ }
+
+ upb_fieldtype_t field_type = self->field_type;
+ size_t elem_size = native_slot_size(field_type);
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += elem_size) {
+ void* self_mem = ((uint8_t *)self->elements) + off;
+ void* other_mem = ((uint8_t *)other->elements) + off;
+ if (!native_slot_eq(field_type, self_mem, other_mem)) {
+ return Qfalse;
+ }
+ }
+ return Qtrue;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.hash => hash_value
+ *
+ * Returns a hash value computed from this repeated field's elements.
+ */
+VALUE RepeatedField_hash(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+
+ VALUE hash = LL2NUM(0);
+
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+ size_t elem_size = native_slot_size(field_type);
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += elem_size) {
+ void* mem = ((uint8_t *)self->elements) + off;
+ VALUE elem = native_slot_get(field_type, field_type_class, mem);
+ hash = rb_funcall(hash, rb_intern("<<"), 1, INT2NUM(2));
+ hash = rb_funcall(hash, rb_intern("^"), 1,
+ rb_funcall(elem, rb_intern("hash"), 0));
+ }
+
+ return hash;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.inspect => string
+ *
+ * Returns a string representing this repeated field's elements. It will be
+ * formated as "[<element>, <element>, ...]", with each element's string
+ * representation computed by its own #inspect method.
+ */
+VALUE RepeatedField_inspect(VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+
+ VALUE str = rb_str_new2("[");
+
+ bool first = true;
+
+ upb_fieldtype_t field_type = self->field_type;
+ VALUE field_type_class = self->field_type_class;
+ size_t elem_size = native_slot_size(field_type);
+ size_t off = 0;
+ for (int i = 0; i < self->size; i++, off += elem_size) {
+ void* mem = ((uint8_t *)self->elements) + off;
+ VALUE elem = native_slot_get(field_type, field_type_class, mem);
+ if (!first) {
+ str = rb_str_cat2(str, ", ");
+ } else {
+ first = false;
+ }
+ str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
+ }
+
+ str = rb_str_cat2(str, "]");
+ return str;
+}
+
+/*
+ * call-seq:
+ * RepeatedField.+(other) => repeated field
+ *
+ * Returns a new repeated field that contains the concatenated list of this
+ * repeated field's elements and other's elements. The other (second) list may
+ * be either another repeated field or a Ruby array.
+ */
+VALUE RepeatedField_plus(VALUE _self, VALUE list) {
+ VALUE dupped = RepeatedField_dup(_self);
+
+ if (TYPE(list) == T_ARRAY) {
+ for (int i = 0; i < RARRAY_LEN(list); i++) {
+ VALUE elem = rb_ary_entry(list, i);
+ RepeatedField_push(dupped, elem);
+ }
+ } else if (RB_TYPE_P(list, T_DATA) && RTYPEDDATA_P(list) &&
+ RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
+ if (self->field_type != list_rptfield->field_type ||
+ self->field_type_class != list_rptfield->field_type_class) {
+ rb_raise(rb_eArgError,
+ "Attempt to append RepeatedField with different element type.");
+ }
+ for (int i = 0; i < list_rptfield->size; i++) {
+ void* mem = RepeatedField_index_native(list, i);
+ RepeatedField_push_native(dupped, mem);
+ }
+ } else {
+ rb_raise(rb_eArgError, "Unknown type appending to RepeatedField");
+ }
+
+ return dupped;
+}
+
+static void validate_type_class(upb_fieldtype_t type, VALUE klass) {
+ if (rb_iv_get(klass, kDescriptorInstanceVar) == Qnil) {
+ rb_raise(rb_eArgError,
+ "Type class has no descriptor. Please pass a "
+ "class or enum as returned by the DescriptorPool.");
+ }
+ if (type == UPB_TYPE_MESSAGE) {
+ VALUE desc = rb_iv_get(klass, kDescriptorInstanceVar);
+ if (!RB_TYPE_P(desc, T_DATA) || !RTYPEDDATA_P(desc) ||
+ RTYPEDDATA_TYPE(desc) != &_Descriptor_type) {
+ rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
+ }
+ if (rb_get_alloc_func(klass) != &Message_alloc) {
+ rb_raise(rb_eArgError,
+ "Message class was not returned by the DescriptorPool.");
+ }
+ } else if (type == UPB_TYPE_ENUM) {
+ VALUE enumdesc = rb_iv_get(klass, kDescriptorInstanceVar);
+ if (!RB_TYPE_P(enumdesc, T_DATA) || !RTYPEDDATA_P(enumdesc) ||
+ RTYPEDDATA_TYPE(enumdesc) != &_EnumDescriptor_type) {
+ rb_raise(rb_eArgError, "Descriptor has an incorrect type.");
+ }
+ }
+}
+
+void RepeatedField_init_args(int argc, VALUE* argv,
+ VALUE _self) {
+ RepeatedField* self = ruby_to_RepeatedField(_self);
+ VALUE ary = Qnil;
+ if (argc < 1) {
+ rb_raise(rb_eArgError, "Expected at least 1 argument.");
+ }
+ self->field_type = ruby_to_fieldtype(argv[0]);
+
+ if (self->field_type == UPB_TYPE_MESSAGE ||
+ self->field_type == UPB_TYPE_ENUM) {
+ if (argc < 2) {
+ rb_raise(rb_eArgError, "Expected at least 2 arguments for message/enum.");
+ }
+ self->field_type_class = argv[1];
+ if (argc > 2) {
+ ary = argv[2];
+ }
+ validate_type_class(self->field_type, self->field_type_class);
+ } else {
+ if (argc > 2) {
+ rb_raise(rb_eArgError, "Too many arguments: expected 1 or 2.");
+ }
+ if (argc > 1) {
+ ary = argv[1];
+ }
+ }
+
+ if (ary != Qnil) {
+ if (!RB_TYPE_P(ary, T_ARRAY)) {
+ rb_raise(rb_eArgError, "Expected array as initialize argument");
+ }
+ for (int i = 0; i < RARRAY_LEN(ary); i++) {
+ RepeatedField_push(_self, rb_ary_entry(ary, i));
+ }
+ }
+}
+
+// Mark, free, alloc, init and class setup functions.
+
+void RepeatedField_mark(void* _self) {
+ RepeatedField* self = (RepeatedField*)_self;
+ rb_gc_mark(self->field_type_class);
+ upb_fieldtype_t field_type = self->field_type;
+ int element_size = native_slot_size(field_type);
+ for (int i = 0; i < self->size; i++) {
+ void* memory = (((uint8_t *)self->elements) + i * element_size);
+ native_slot_mark(self->field_type, memory);
+ }
+}
+
+void RepeatedField_free(void* _self) {
+ RepeatedField* self = (RepeatedField*)_self;
+ xfree(self->elements);
+ xfree(self);
+}
+
+/*
+ * call-seq:
+ * RepeatedField.new(type, type_class = nil, initial_elems = [])
+ *
+ * Creates a new repeated field. The provided type must be a Ruby symbol, and
+ * can take on the same values as those accepted by FieldDescriptor#type=. If
+ * the type is :message or :enum, type_class must be non-nil, and must be the
+ * Ruby class or module returned by Descriptor#msgclass or
+ * EnumDescriptor#enummodule, respectively. An initial list of elements may also
+ * be provided.
+ */
+VALUE RepeatedField_alloc(VALUE klass) {
+ RepeatedField* self = ALLOC(RepeatedField);
+ self->elements = NULL;
+ self->size = 0;
+ self->capacity = 0;
+ self->field_type = -1;
+ self->field_type_class = Qnil;
+ VALUE ret = TypedData_Wrap_Struct(klass, &RepeatedField_type, self);
+ return ret;
+}
+
+VALUE RepeatedField_init(int argc, VALUE* argv, VALUE self) {
+ RepeatedField_init_args(argc, argv, self);
+ return Qnil;
+}
+
+void RepeatedField_register(VALUE module) {
+ VALUE klass = rb_define_class_under(
+ module, "RepeatedField", rb_cObject);
+ rb_define_alloc_func(klass, RepeatedField_alloc);
+ cRepeatedField = klass;
+ rb_gc_register_address(&cRepeatedField);
+
+ rb_define_method(klass, "initialize",
+ RepeatedField_init, -1);
+ rb_define_method(klass, "each", RepeatedField_each, 0);
+ rb_define_method(klass, "[]", RepeatedField_index, 1);
+ rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
+ rb_define_method(klass, "push", RepeatedField_push, 1);
+ rb_define_method(klass, "<<", RepeatedField_push, 1);
+ rb_define_method(klass, "pop", RepeatedField_pop, 0);
+ rb_define_method(klass, "insert", RepeatedField_insert, -1);
+ rb_define_method(klass, "replace", RepeatedField_replace, 1);
+ rb_define_method(klass, "clear", RepeatedField_clear, 0);
+ rb_define_method(klass, "length", RepeatedField_length, 0);
+ rb_define_method(klass, "dup", RepeatedField_dup, 0);
+ // Also define #clone so that we don't inherit Object#clone.
+ rb_define_method(klass, "clone", RepeatedField_dup, 0);
+ rb_define_method(klass, "==", RepeatedField_eq, 1);
+ rb_define_method(klass, "hash", RepeatedField_hash, 0);
+ rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
+ rb_define_method(klass, "+", RepeatedField_plus, 1);
+ rb_include_module(klass, rb_mEnumerable);
+}
diff --git a/ruby/ext/protobuf_c/storage.c b/ruby/ext/protobuf_c/storage.c
new file mode 100644
index 00000000..c4d801af
--- /dev/null
+++ b/ruby/ext/protobuf_c/storage.c
@@ -0,0 +1,577 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "protobuf.h"
+
+#include <math.h>
+
+#include <ruby/encoding.h>
+
+// -----------------------------------------------------------------------------
+// Ruby <-> native slot management.
+// -----------------------------------------------------------------------------
+
+#define DEREF(memory, type) *(type*)(memory)
+
+size_t native_slot_size(upb_fieldtype_t type) {
+ switch (type) {
+ case UPB_TYPE_FLOAT: return 4;
+ case UPB_TYPE_DOUBLE: return 8;
+ case UPB_TYPE_BOOL: return 1;
+ case UPB_TYPE_STRING: return sizeof(VALUE);
+ case UPB_TYPE_BYTES: return sizeof(VALUE);
+ case UPB_TYPE_MESSAGE: return sizeof(VALUE);
+ case UPB_TYPE_ENUM: return 4;
+ case UPB_TYPE_INT32: return 4;
+ case UPB_TYPE_INT64: return 8;
+ case UPB_TYPE_UINT32: return 4;
+ case UPB_TYPE_UINT64: return 8;
+ default: return 0;
+ }
+}
+
+static void check_int_range_precision(upb_fieldtype_t type, VALUE val) {
+ // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
+ // bound; we just need to do precision checks (i.e., disallow rounding) and
+ // check for < 0 on unsigned types.
+ if (TYPE(val) == T_FLOAT) {
+ double dbl_val = NUM2DBL(val);
+ if (floor(dbl_val) != dbl_val) {
+ rb_raise(rb_eRangeError,
+ "Non-integral floating point value assigned to integer field.");
+ }
+ }
+ if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
+ if (NUM2DBL(val) < 0) {
+ rb_raise(rb_eRangeError,
+ "Assigning negative value to unsigned integer field.");
+ }
+ }
+}
+
+static bool is_ruby_num(VALUE value) {
+ return (TYPE(value) == T_FLOAT ||
+ TYPE(value) == T_FIXNUM ||
+ TYPE(value) == T_BIGNUM);
+}
+
+void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
+ bool bad_encoding = false;
+ rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
+ if (type == UPB_TYPE_STRING) {
+ bad_encoding =
+ string_encoding != kRubyStringUtf8Encoding &&
+ string_encoding != kRubyStringASCIIEncoding;
+ } else {
+ bad_encoding =
+ string_encoding != kRubyString8bitEncoding;
+ }
+ // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT
+ // (for bytes fields).
+ if (bad_encoding) {
+ rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)",
+ (type == UPB_TYPE_STRING) ? "string" : "bytes",
+ (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT",
+ rb_enc_name(string_encoding));
+ }
+}
+
+void native_slot_set(upb_fieldtype_t type, VALUE type_class,
+ void* memory, VALUE value) {
+ switch (type) {
+ case UPB_TYPE_FLOAT:
+ if (!is_ruby_num(value)) {
+ rb_raise(rb_eTypeError, "Expected number type for float field.");
+ }
+ DEREF(memory, float) = NUM2DBL(value);
+ break;
+ case UPB_TYPE_DOUBLE:
+ if (!is_ruby_num(value)) {
+ rb_raise(rb_eTypeError, "Expected number type for double field.");
+ }
+ DEREF(memory, double) = NUM2DBL(value);
+ break;
+ case UPB_TYPE_BOOL: {
+ int8_t val = -1;
+ if (value == Qtrue) {
+ val = 1;
+ } else if (value == Qfalse) {
+ val = 0;
+ } else {
+ rb_raise(rb_eTypeError, "Invalid argument for boolean field.");
+ }
+ DEREF(memory, int8_t) = val;
+ break;
+ }
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ if (CLASS_OF(value) != rb_cString) {
+ rb_raise(rb_eTypeError, "Invalid argument for string field.");
+ }
+ native_slot_validate_string_encoding(type, value);
+ DEREF(memory, VALUE) = value;
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ if (CLASS_OF(value) != type_class) {
+ rb_raise(rb_eTypeError,
+ "Invalid type %s to assign to submessage field.",
+ rb_class2name(CLASS_OF(value)));
+ }
+ DEREF(memory, VALUE) = value;
+ break;
+ }
+ case UPB_TYPE_ENUM: {
+ if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
+ rb_raise(rb_eTypeError,
+ "Expected number or symbol type for enum field.");
+ }
+ int32_t int_val = 0;
+ if (TYPE(value) == T_SYMBOL) {
+ // Ensure that the given symbol exists in the enum module.
+ VALUE lookup = rb_const_get(type_class, SYM2ID(value));
+ if (lookup == Qnil) {
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
+ } else {
+ int_val = NUM2INT(lookup);
+ }
+ } else {
+ check_int_range_precision(UPB_TYPE_INT32, value);
+ int_val = NUM2INT(value);
+ }
+ DEREF(memory, int32_t) = int_val;
+ break;
+ }
+ case UPB_TYPE_INT32:
+ case UPB_TYPE_INT64:
+ case UPB_TYPE_UINT32:
+ case UPB_TYPE_UINT64:
+ if (!is_ruby_num(value)) {
+ rb_raise(rb_eTypeError, "Expected number type for integral field.");
+ }
+ check_int_range_precision(type, value);
+ switch (type) {
+ case UPB_TYPE_INT32:
+ DEREF(memory, int32_t) = NUM2INT(value);
+ break;
+ case UPB_TYPE_INT64:
+ DEREF(memory, int64_t) = NUM2LL(value);
+ break;
+ case UPB_TYPE_UINT32:
+ DEREF(memory, uint32_t) = NUM2UINT(value);
+ break;
+ case UPB_TYPE_UINT64:
+ DEREF(memory, uint64_t) = NUM2ULL(value);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+VALUE native_slot_get(upb_fieldtype_t type, VALUE type_class, void* memory) {
+ switch (type) {
+ case UPB_TYPE_FLOAT:
+ return DBL2NUM(DEREF(memory, float));
+ case UPB_TYPE_DOUBLE:
+ return DBL2NUM(DEREF(memory, double));
+ case UPB_TYPE_BOOL:
+ return DEREF(memory, int8_t) ? Qtrue : Qfalse;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ return *((VALUE *)memory);
+ case UPB_TYPE_ENUM: {
+ int32_t val = DEREF(memory, int32_t);
+ VALUE symbol = enum_lookup(type_class, INT2NUM(val));
+ if (symbol == Qnil) {
+ return INT2NUM(val);
+ } else {
+ return symbol;
+ }
+ }
+ case UPB_TYPE_INT32:
+ return INT2NUM(DEREF(memory, int32_t));
+ case UPB_TYPE_INT64:
+ return LL2NUM(DEREF(memory, int64_t));
+ case UPB_TYPE_UINT32:
+ return UINT2NUM(DEREF(memory, uint32_t));
+ case UPB_TYPE_UINT64:
+ return ULL2NUM(DEREF(memory, uint64_t));
+ default:
+ return Qnil;
+ }
+}
+
+void native_slot_init(upb_fieldtype_t type, void* memory) {
+ switch (type) {
+ case UPB_TYPE_FLOAT:
+ DEREF(memory, float) = 0.0;
+ break;
+ case UPB_TYPE_DOUBLE:
+ DEREF(memory, double) = 0.0;
+ break;
+ case UPB_TYPE_BOOL:
+ DEREF(memory, int8_t) = 0;
+ break;
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ // TODO(cfallin): set encoding appropriately
+ DEREF(memory, VALUE) = rb_str_new2("");
+ break;
+ case UPB_TYPE_MESSAGE:
+ DEREF(memory, VALUE) = Qnil;
+ break;
+ case UPB_TYPE_ENUM:
+ case UPB_TYPE_INT32:
+ DEREF(memory, int32_t) = 0;
+ break;
+ case UPB_TYPE_INT64:
+ DEREF(memory, int64_t) = 0;
+ break;
+ case UPB_TYPE_UINT32:
+ DEREF(memory, uint32_t) = 0;
+ break;
+ case UPB_TYPE_UINT64:
+ DEREF(memory, uint64_t) = 0;
+ break;
+ default:
+ break;
+ }
+}
+
+void native_slot_mark(upb_fieldtype_t type, void* memory) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE:
+ rb_gc_mark(DEREF(memory, VALUE));
+ break;
+ default:
+ break;
+ }
+}
+
+void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
+ memcpy(to, from, native_slot_size(type));
+}
+
+void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES: {
+ VALUE from_val = DEREF(from, VALUE);
+ DEREF(to, VALUE) = (from_val != Qnil) ?
+ rb_funcall(from_val, rb_intern("dup"), 0) : Qnil;
+ break;
+ }
+ case UPB_TYPE_MESSAGE: {
+ VALUE from_val = DEREF(from, VALUE);
+ DEREF(to, VALUE) = (from_val != Qnil) ?
+ Message_deep_copy(from_val) : Qnil;
+ break;
+ }
+ default:
+ memcpy(to, from, native_slot_size(type));
+ }
+}
+
+bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
+ switch (type) {
+ case UPB_TYPE_STRING:
+ case UPB_TYPE_BYTES:
+ case UPB_TYPE_MESSAGE: {
+ VALUE val1 = DEREF(mem1, VALUE);
+ VALUE val2 = DEREF(mem2, VALUE);
+ VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
+ return ret == Qtrue;
+ }
+ default:
+ return !memcmp(mem1, mem2, native_slot_size(type));
+ }
+}
+
+// -----------------------------------------------------------------------------
+// Memory layout management.
+// -----------------------------------------------------------------------------
+
+MessageLayout* create_layout(const upb_msgdef* msgdef) {
+ MessageLayout* layout = ALLOC(MessageLayout);
+ int nfields = upb_msgdef_numfields(msgdef);
+ layout->offsets = ALLOC_N(size_t, nfields);
+
+ upb_msg_iter it;
+ size_t off = 0;
+ for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ size_t field_size =
+ (upb_fielddef_label(field) == UPB_LABEL_REPEATED) ?
+ sizeof(VALUE) : native_slot_size(upb_fielddef_type(field));
+ // align current offset
+ off = (off + field_size - 1) & ~(field_size - 1);
+ layout->offsets[upb_fielddef_index(field)] = off;
+ off += field_size;
+ }
+
+ layout->size = off;
+
+ layout->msgdef = msgdef;
+ upb_msgdef_ref(layout->msgdef, &layout->msgdef);
+
+ return layout;
+}
+
+void free_layout(MessageLayout* layout) {
+ xfree(layout->offsets);
+ upb_msgdef_unref(layout->msgdef, &layout->msgdef);
+ xfree(layout);
+}
+
+static VALUE get_type_class(const upb_fielddef* field) {
+ VALUE type_class = Qnil;
+ if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+ VALUE submsgdesc =
+ get_def_obj(upb_fielddef_subdef(field));
+ type_class = Descriptor_msgclass(submsgdesc);
+ } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
+ VALUE subenumdesc =
+ get_def_obj(upb_fielddef_subdef(field));
+ type_class = EnumDescriptor_enummodule(subenumdesc);
+ }
+ return type_class;
+}
+
+VALUE layout_get(MessageLayout* layout,
+ void* storage,
+ const upb_fielddef* field) {
+ void* memory = ((uint8_t *)storage) +
+ layout->offsets[upb_fielddef_index(field)];
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ return *((VALUE *)memory);
+ } else {
+ return native_slot_get(upb_fielddef_type(field),
+ get_type_class(field),
+ memory);
+ }
+}
+
+static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
+ assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
+
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
+ RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
+ rb_raise(rb_eTypeError, "Expected repeated field array");
+ }
+
+ RepeatedField* self = ruby_to_RepeatedField(val);
+ if (self->field_type != upb_fielddef_type(field)) {
+ rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
+ }
+
+ if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE ||
+ upb_fielddef_type(field) == UPB_TYPE_ENUM) {
+ RepeatedField* self = ruby_to_RepeatedField(val);
+ if (self->field_type_class !=
+ get_def_obj(upb_fielddef_subdef(field))) {
+ rb_raise(rb_eTypeError,
+ "Repeated field array has wrong message/enum class");
+ }
+ }
+}
+
+void layout_set(MessageLayout* layout,
+ void* storage,
+ const upb_fielddef* field,
+ VALUE val) {
+ void* memory = ((uint8_t *)storage) +
+ layout->offsets[upb_fielddef_index(field)];
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ check_repeated_field_type(val, field);
+ *((VALUE *)memory) = val;
+ } else {
+ native_slot_set(upb_fielddef_type(field), get_type_class(field),
+ memory, val);
+ }
+}
+
+void layout_init(MessageLayout* layout,
+ void* storage) {
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ void* memory = ((uint8_t *)storage) +
+ layout->offsets[upb_fielddef_index(field)];
+
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ VALUE ary = Qnil;
+ VALUE type_class = get_type_class(field);
+ if (type_class != Qnil) {
+ VALUE args[2] = {
+ fieldtype_to_ruby(upb_fielddef_type(field)),
+ type_class,
+ };
+ ary = rb_class_new_instance(2, args, cRepeatedField);
+ } else {
+ VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
+ ary = rb_class_new_instance(1, args, cRepeatedField);
+ }
+ *((VALUE *)memory) = ary;
+ } else {
+ native_slot_init(upb_fielddef_type(field), memory);
+ }
+ }
+}
+
+void layout_mark(MessageLayout* layout, void* storage) {
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ void* memory = ((uint8_t *)storage) +
+ layout->offsets[upb_fielddef_index(field)];
+
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ rb_gc_mark(*((VALUE *)memory));
+ } else {
+ native_slot_mark(upb_fielddef_type(field), memory);
+ }
+ }
+}
+
+void layout_dup(MessageLayout* layout, void* to, void* from) {
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ void* to_memory = ((uint8_t *)to) +
+ layout->offsets[upb_fielddef_index(field)];
+ void* from_memory = ((uint8_t *)from) +
+ layout->offsets[upb_fielddef_index(field)];
+
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ *((VALUE *)to_memory) = RepeatedField_dup(*((VALUE *)from_memory));
+ } else {
+ native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
+ }
+ }
+}
+
+void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ void* to_memory = ((uint8_t *)to) +
+ layout->offsets[upb_fielddef_index(field)];
+ void* from_memory = ((uint8_t *)from) +
+ layout->offsets[upb_fielddef_index(field)];
+
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ *((VALUE *)to_memory) = RepeatedField_deep_copy(*((VALUE *)from_memory));
+ } else {
+ native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
+ }
+ }
+}
+
+VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
+ upb_msg_iter it;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ void* msg1_memory = ((uint8_t *)msg1) +
+ layout->offsets[upb_fielddef_index(field)];
+ void* msg2_memory = ((uint8_t *)msg2) +
+ layout->offsets[upb_fielddef_index(field)];
+
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ if (RepeatedField_eq(*((VALUE *)msg1_memory),
+ *((VALUE *)msg2_memory)) == Qfalse) {
+ return Qfalse;
+ }
+ } else {
+ if (!native_slot_eq(upb_fielddef_type(field),
+ msg1_memory, msg2_memory)) {
+ return Qfalse;
+ }
+ }
+ }
+ return Qtrue;
+}
+
+VALUE layout_hash(MessageLayout* layout, void* storage) {
+ upb_msg_iter it;
+ st_index_t h = rb_hash_start(0);
+ VALUE hash_sym = rb_intern("hash");
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ VALUE field_val = layout_get(layout, storage, field);
+ h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
+ }
+ h = rb_hash_end(h);
+
+ return INT2FIX(h);
+}
+
+VALUE layout_inspect(MessageLayout* layout, void* storage) {
+ VALUE str = rb_str_new2("");
+
+ upb_msg_iter it;
+ bool first = true;
+ for (upb_msg_begin(&it, layout->msgdef);
+ !upb_msg_done(&it);
+ upb_msg_next(&it)) {
+ const upb_fielddef* field = upb_msg_iter_field(&it);
+ VALUE field_val = layout_get(layout, storage, field);
+
+ if (!first) {
+ str = rb_str_cat2(str, ", ");
+ } else {
+ first = false;
+ }
+ str = rb_str_cat2(str, upb_fielddef_name(field));
+ str = rb_str_cat2(str, ": ");
+
+ str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
+ }
+
+ return str;
+}
diff --git a/ruby/lib/protobuf.rb b/ruby/lib/protobuf.rb
new file mode 100644
index 00000000..2ace48f9
--- /dev/null
+++ b/ruby/lib/protobuf.rb
@@ -0,0 +1,31 @@
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc. All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+require 'protobuf_c'
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
new file mode 100644
index 00000000..237fbb06
--- /dev/null
+++ b/ruby/tests/basic.rb
@@ -0,0 +1,633 @@
+#!/usr/bin/ruby
+
+require 'protobuf'
+require 'test/unit'
+
+# ------------- generated code --------------
+
+module BasicTest
+ pool = Google::Protobuf::DescriptorPool.new
+ pool.build do
+ add_message "TestMessage" do
+ optional :optional_int32, :int32, 1
+ optional :optional_int64, :int64, 2
+ optional :optional_uint32, :uint32, 3
+ optional :optional_uint64, :uint64, 4
+ optional :optional_bool, :bool, 5
+ optional :optional_float, :float, 6
+ optional :optional_double, :double, 7
+ optional :optional_string, :string, 8
+ optional :optional_bytes, :bytes, 9
+ optional :optional_msg, :message, 10, "TestMessage2"
+ optional :optional_enum, :enum, 11, "TestEnum"
+
+ repeated :repeated_int32, :int32, 12
+ repeated :repeated_int64, :int64, 13
+ repeated :repeated_uint32, :uint32, 14
+ repeated :repeated_uint64, :uint64, 15
+ repeated :repeated_bool, :bool, 16
+ repeated :repeated_float, :float, 17
+ repeated :repeated_double, :double, 18
+ repeated :repeated_string, :string, 19
+ repeated :repeated_bytes, :bytes, 20
+ repeated :repeated_msg, :message, 21, "TestMessage2"
+ repeated :repeated_enum, :enum, 22, "TestEnum"
+ end
+ add_message "TestMessage2" do
+ optional :foo, :int32, 1
+ end
+ add_message "Recursive1" do
+ optional :foo, :message, 1, "Recursive2"
+ end
+ add_message "Recursive2" do
+ optional :foo, :message, 1, "Recursive1"
+ end
+ add_enum "TestEnum" do
+ value :Default, 0
+ value :A, 1
+ value :B, 2
+ value :C, 3
+ end
+ add_message "BadFieldNames" do
+ optional :dup, :int32, 1
+ optional :class, :int32, 2
+ optional :"a.b", :int32, 3
+ end
+ end
+
+ TestMessage = pool.lookup("TestMessage").msgclass
+ TestMessage2 = pool.lookup("TestMessage2").msgclass
+ Recursive1 = pool.lookup("Recursive1").msgclass
+ Recursive2 = pool.lookup("Recursive2").msgclass
+ TestEnum = pool.lookup("TestEnum").enummodule
+ BadFieldNames = pool.lookup("BadFieldNames").msgclass
+
+# ------------ test cases ---------------
+
+ class MessageContainerTest < Test::Unit::TestCase
+
+ def test_defaults
+ m = TestMessage.new
+ assert m.optional_int32 == 0
+ assert m.optional_int64 == 0
+ assert m.optional_uint32 == 0
+ assert m.optional_uint64 == 0
+ assert m.optional_bool == false
+ assert m.optional_float == 0.0
+ assert m.optional_double == 0.0
+ assert m.optional_string == ""
+ assert m.optional_bytes == ""
+ assert m.optional_msg == nil
+ assert m.optional_enum == :Default
+ end
+
+ def test_setters
+ m = TestMessage.new
+ m.optional_int32 = -42
+ assert m.optional_int32 == -42
+ m.optional_int64 = -0x1_0000_0000
+ assert m.optional_int64 == -0x1_0000_0000
+ m.optional_uint32 = 0x9000_0000
+ assert m.optional_uint32 == 0x9000_0000
+ m.optional_uint64 = 0x9000_0000_0000_0000
+ assert m.optional_uint64 == 0x9000_0000_0000_0000
+ m.optional_bool = true
+ assert m.optional_bool == true
+ m.optional_float = 0.5
+ assert m.optional_float == 0.5
+ m.optional_double = 0.5
+ m.optional_string = "hello"
+ assert m.optional_string == "hello"
+ m.optional_bytes = "world".encode!('ASCII-8BIT')
+ assert m.optional_bytes == "world"
+ m.optional_msg = TestMessage2.new(:foo => 42)
+ assert m.optional_msg == TestMessage2.new(:foo => 42)
+ end
+
+ def test_ctor_args
+ m = TestMessage.new(:optional_int32 => -42,
+ :optional_msg => TestMessage2.new,
+ :optional_enum => :C,
+ :repeated_string => ["hello", "there", "world"])
+ assert m.optional_int32 == -42
+ assert m.optional_msg.class == TestMessage2
+ assert m.repeated_string.length == 3
+ assert m.optional_enum == :C
+ assert m.repeated_string[0] == "hello"
+ assert m.repeated_string[1] == "there"
+ assert m.repeated_string[2] == "world"
+ end
+
+ def test_inspect
+ m = TestMessage.new(:optional_int32 => -42,
+ :optional_enum => :A,
+ :optional_msg => TestMessage2.new,
+ :repeated_string => ["hello", "there", "world"])
+ expected = '<BasicTest::TestMessage: optional_int32: -42, optional_int64: 0, optional_uint32: 0, optional_uint64: 0, optional_bool: false, optional_float: 0.0, optional_double: 0.0, optional_string: "", optional_bytes: "", optional_msg: <BasicTest::TestMessage2: foo: 0>, optional_enum: :A, repeated_int32: [], repeated_int64: [], repeated_uint32: [], repeated_uint64: [], repeated_bool: [], repeated_float: [], repeated_double: [], repeated_string: ["hello", "there", "world"], repeated_bytes: [], repeated_msg: [], repeated_enum: []>'
+ assert m.inspect == expected
+ end
+
+ def test_hash
+ m1 = TestMessage.new(:optional_int32 => 42)
+ m2 = TestMessage.new(:optional_int32 => 102)
+ assert m1.hash != 0
+ assert m2.hash != 0
+ # relying on the randomness here -- if hash function changes and we are
+ # unlucky enough to get a collision, then change the values above.
+ assert m1.hash != m2.hash
+ end
+
+ def test_type_errors
+ m = TestMessage.new
+ assert_raise TypeError do
+ m.optional_int32 = "hello"
+ end
+ assert_raise TypeError do
+ m.optional_string = 42
+ end
+ assert_raise TypeError do
+ m.optional_string = nil
+ end
+ assert_raise TypeError do
+ m.optional_bool = 42
+ end
+ assert_raise TypeError do
+ m.optional_msg = TestMessage.new # expects TestMessage2
+ end
+
+ assert_raise TypeError do
+ m.repeated_int32 = [] # needs RepeatedField
+ end
+
+ assert_raise TypeError do
+ m.repeated_int32.push "hello"
+ end
+
+ assert_raise TypeError do
+ m.repeated_msg.push TestMessage.new
+ end
+ end
+
+ def test_string_encoding
+ m = TestMessage.new
+
+ # Assigning a normal (ASCII or UTF8) string to a bytes field, or
+ # ASCII-8BIT to a string field, raises an error.
+ assert_raise TypeError do
+ m.optional_bytes = "Test string ASCII".encode!('ASCII')
+ end
+ assert_raise TypeError do
+ m.optional_bytes = "Test string UTF-8 \u0100".encode!('UTF-8')
+ end
+ assert_raise TypeError do
+ m.optional_string = ["FFFF"].pack('H*')
+ end
+
+ # "Ordinary" use case.
+ m.optional_bytes = ["FFFF"].pack('H*')
+ m.optional_string = "\u0100"
+
+ # strings are mutable so we can do this, but serialize should catch it.
+ m.optional_string = "asdf".encode!('UTF-8')
+ m.optional_string.encode!('ASCII-8BIT')
+ assert_raise TypeError do
+ data = TestMessage.encode(m)
+ end
+ end
+
+ def test_rptfield_int32
+ l = Google::Protobuf::RepeatedField.new(:int32)
+ assert l.count == 0
+ l = Google::Protobuf::RepeatedField.new(:int32, [1, 2, 3])
+ assert l.count == 3
+ assert l == [1, 2, 3]
+ l.push 4
+ assert l == [1, 2, 3, 4]
+ dst_list = []
+ l.each { |val| dst_list.push val }
+ assert dst_list == [1, 2, 3, 4]
+ assert l.to_a == [1, 2, 3, 4]
+ assert l[0] == 1
+ assert l[3] == 4
+ l[0] = 5
+ assert l == [5, 2, 3, 4]
+
+ l2 = l.dup
+ assert l == l2
+ assert l.object_id != l2.object_id
+ l2.push 6
+ assert l.count == 4
+ assert l2.count == 5
+
+ assert l.inspect == '[5, 2, 3, 4]'
+
+ l.insert(7, 8, 9)
+ assert l == [5, 2, 3, 4, 7, 8, 9]
+ assert l.pop == 9
+ assert l == [5, 2, 3, 4, 7, 8]
+
+ assert_raise TypeError do
+ m = TestMessage.new
+ l.push m
+ end
+
+ m = TestMessage.new
+ m.repeated_int32 = l
+ assert m.repeated_int32 == [5, 2, 3, 4, 7, 8]
+ assert m.repeated_int32.object_id == l.object_id
+ l.push 42
+ assert m.repeated_int32.pop == 42
+
+ l3 = l + l.dup
+ assert l3.count == l.count * 2
+ l.count.times do |i|
+ assert l3[i] == l[i]
+ assert l3[l.count + i] == l[i]
+ end
+
+ l.clear
+ assert l.count == 0
+ l += [1, 2, 3, 4]
+ l.replace([5, 6, 7, 8])
+ assert l == [5, 6, 7, 8]
+
+ l4 = Google::Protobuf::RepeatedField.new(:int32)
+ l4[5] = 42
+ assert l4 == [0, 0, 0, 0, 0, 42]
+
+ l4 << 100
+ assert l4 == [0, 0, 0, 0, 0, 42, 100]
+ l4 << 101 << 102
+ assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
+ end
+
+ def test_rptfield_msg
+ l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
+ l.push TestMessage.new
+ assert l.count == 1
+ assert_raise TypeError do
+ l.push TestMessage2.new
+ end
+ assert_raise TypeError do
+ l.push 42
+ end
+
+ l2 = l.dup
+ assert l2[0] == l[0]
+ assert l2[0].object_id == l[0].object_id
+
+ l2 = Google::Protobuf.deep_copy(l)
+ assert l2[0] == l[0]
+ assert l2[0].object_id != l[0].object_id
+
+ l3 = l + l2
+ assert l3.count == 2
+ assert l3[0] == l[0]
+ assert l3[1] == l2[0]
+ l3[0].optional_int32 = 1000
+ assert l[0].optional_int32 == 1000
+
+ new_msg = TestMessage.new(:optional_int32 => 200)
+ l4 = l + [new_msg]
+ assert l4.count == 2
+ new_msg.optional_int32 = 1000
+ assert l4[1].optional_int32 == 1000
+ end
+
+ def test_rptfield_enum
+ l = Google::Protobuf::RepeatedField.new(:enum, TestEnum)
+ l.push :A
+ l.push :B
+ l.push :C
+ assert l.count == 3
+ assert_raise NameError do
+ l.push :D
+ end
+ assert l[0] == :A
+
+ l.push 4
+ assert l[3] == 4
+ end
+
+ def test_rptfield_initialize
+ assert_raise ArgumentError do
+ l = Google::Protobuf::RepeatedField.new
+ end
+ assert_raise ArgumentError do
+ l = Google::Protobuf::RepeatedField.new(:message)
+ end
+ assert_raise ArgumentError do
+ l = Google::Protobuf::RepeatedField.new([1, 2, 3])
+ end
+ assert_raise ArgumentError do
+ l = Google::Protobuf::RepeatedField.new(:message, [TestMessage2.new])
+ end
+ end
+
+ def test_enum_field
+ m = TestMessage.new
+ assert m.optional_enum == :Default
+ m.optional_enum = :A
+ assert m.optional_enum == :A
+ assert_raise NameError do
+ m.optional_enum = :ASDF
+ end
+ m.optional_enum = 1
+ assert m.optional_enum == :A
+ m.optional_enum = 100
+ assert m.optional_enum == 100
+ end
+
+ def test_dup
+ m = TestMessage.new
+ m.optional_string = "hello"
+ m.optional_int32 = 42
+ m.repeated_msg.push TestMessage2.new(:foo => 100)
+ m.repeated_msg.push TestMessage2.new(:foo => 200)
+
+ m2 = m.dup
+ assert m == m2
+ m.optional_int32 += 1
+ assert m != m2
+ assert m.repeated_msg[0] == m2.repeated_msg[0]
+ assert m.repeated_msg[0].object_id == m2.repeated_msg[0].object_id
+ end
+
+ def test_deep_copy
+ m = TestMessage.new(:optional_int32 => 42,
+ :repeated_msg => [TestMessage2.new(:foo => 100)])
+ m2 = Google::Protobuf.deep_copy(m)
+ assert m == m2
+ assert m.repeated_msg == m2.repeated_msg
+ assert m.repeated_msg.object_id != m2.repeated_msg.object_id
+ assert m.repeated_msg[0].object_id != m2.repeated_msg[0].object_id
+ end
+
+ def test_enum_lookup
+ assert TestEnum::A == 1
+ assert TestEnum::B == 2
+ assert TestEnum::C == 3
+
+ assert TestEnum::lookup(1) == :A
+ assert TestEnum::lookup(2) == :B
+ assert TestEnum::lookup(3) == :C
+
+ assert TestEnum::resolve(:A) == 1
+ assert TestEnum::resolve(:B) == 2
+ assert TestEnum::resolve(:C) == 3
+ end
+
+ def test_parse_serialize
+ m = TestMessage.new(:optional_int32 => 42,
+ :optional_string => "hello world",
+ :optional_enum => :B,
+ :repeated_string => ["a", "b", "c"],
+ :repeated_int32 => [42, 43, 44],
+ :repeated_enum => [:A, :B, :C, 100],
+ :repeated_msg => [TestMessage2.new(:foo => 1), TestMessage2.new(:foo => 2)])
+ data = TestMessage.encode m
+ m2 = TestMessage.decode data
+ assert m == m2
+
+ data = Google::Protobuf.encode m
+ m2 = Google::Protobuf.decode(TestMessage, data)
+ assert m == m2
+ end
+
+ def test_def_errors
+ s = Google::Protobuf::DescriptorPool.new
+ assert_raise TypeError do
+ s.build do
+ # enum with no default (integer value 0)
+ add_enum "MyEnum" do
+ value :A, 1
+ end
+ end
+ end
+ assert_raise TypeError do
+ s.build do
+ # message with required field (unsupported in proto3)
+ add_message "MyMessage" do
+ required :foo, :int32, 1
+ end
+ end
+ end
+ end
+
+ def test_corecursive
+ # just be sure that we can instantiate types with corecursive field-type
+ # references.
+ m = Recursive1.new(:foo => Recursive2.new(:foo => Recursive1.new))
+ assert Recursive1.descriptor.lookup("foo").subtype ==
+ Recursive2.descriptor
+ assert Recursive2.descriptor.lookup("foo").subtype ==
+ Recursive1.descriptor
+
+ serialized = Recursive1.encode(m)
+ m2 = Recursive1.decode(serialized)
+ assert m == m2
+ end
+
+ def test_serialize_cycle
+ m = Recursive1.new(:foo => Recursive2.new)
+ m.foo.foo = m
+ assert_raise RuntimeError do
+ serialized = Recursive1.encode(m)
+ end
+ end
+
+ def test_bad_field_names
+ m = BadFieldNames.new(:dup => 1, :class => 2)
+ m2 = m.dup
+ assert m == m2
+ assert m['dup'] == 1
+ assert m['class'] == 2
+ m['dup'] = 3
+ assert m['dup'] == 3
+ m['a.b'] = 4
+ assert m['a.b'] == 4
+ end
+
+
+ def test_int_ranges
+ m = TestMessage.new
+
+ m.optional_int32 = 0
+ m.optional_int32 = -0x8000_0000
+ m.optional_int32 = +0x7fff_ffff
+ m.optional_int32 = 1.0
+ m.optional_int32 = -1.0
+ m.optional_int32 = 2e9
+ assert_raise RangeError do
+ m.optional_int32 = -0x8000_0001
+ end
+ assert_raise RangeError do
+ m.optional_int32 = +0x8000_0000
+ end
+ assert_raise RangeError do
+ m.optional_int32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+ end
+ assert_raise RangeError do
+ m.optional_int32 = 1e12
+ end
+ assert_raise RangeError do
+ m.optional_int32 = 1.5
+ end
+
+ m.optional_uint32 = 0
+ m.optional_uint32 = +0xffff_ffff
+ m.optional_uint32 = 1.0
+ m.optional_uint32 = 4e9
+ assert_raise RangeError do
+ m.optional_uint32 = -1
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = -1.5
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = -1.5e12
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = -0x1000_0000_0000_0000
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = +0x1_0000_0000
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = 1e12
+ end
+ assert_raise RangeError do
+ m.optional_uint32 = 1.5
+ end
+
+ m.optional_int64 = 0
+ m.optional_int64 = -0x8000_0000_0000_0000
+ m.optional_int64 = +0x7fff_ffff_ffff_ffff
+ m.optional_int64 = 1.0
+ m.optional_int64 = -1.0
+ m.optional_int64 = 8e18
+ m.optional_int64 = -8e18
+ assert_raise RangeError do
+ m.optional_int64 = -0x8000_0000_0000_0001
+ end
+ assert_raise RangeError do
+ m.optional_int64 = +0x8000_0000_0000_0000
+ end
+ assert_raise RangeError do
+ m.optional_int64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+ end
+ assert_raise RangeError do
+ m.optional_int64 = 1e50
+ end
+ assert_raise RangeError do
+ m.optional_int64 = 1.5
+ end
+
+ m.optional_uint64 = 0
+ m.optional_uint64 = +0xffff_ffff_ffff_ffff
+ m.optional_uint64 = 1.0
+ m.optional_uint64 = 16e18
+ assert_raise RangeError do
+ m.optional_uint64 = -1
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = -1.5
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = -1.5e12
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = -0x1_0000_0000_0000_0000
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = +0x1_0000_0000_0000_0000
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = +0x1000_0000_0000_0000_0000_0000 # force Bignum
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = 1e50
+ end
+ assert_raise RangeError do
+ m.optional_uint64 = 1.5
+ end
+
+ end
+
+ def test_stress_test
+ m = TestMessage.new
+ m.optional_int32 = 42
+ m.optional_int64 = 0x100000000
+ m.optional_string = "hello world"
+ 10.times do m.repeated_msg.push TestMessage2.new(:foo => 42) end
+ 10.times do m.repeated_string.push "hello world" end
+
+ data = TestMessage.encode(m)
+
+ l = 0
+ 10_000.times do
+ m = TestMessage.decode(data)
+ data_new = TestMessage.encode(m)
+ assert data_new == data
+ data = data_new
+ end
+ end
+
+ def test_reflection
+ m = TestMessage.new(:optional_int32 => 1234)
+ msgdef = m.class.descriptor
+ assert msgdef.class == Google::Protobuf::Descriptor
+ assert msgdef.any? {|field| field.name == "optional_int32"}
+ optional_int32 = msgdef.lookup "optional_int32"
+ assert optional_int32.class == Google::Protobuf::FieldDescriptor
+ assert optional_int32 != nil
+ assert optional_int32.name == "optional_int32"
+ assert optional_int32.type == :int32
+ optional_int32.set(m, 5678)
+ assert m.optional_int32 == 5678
+ m.optional_int32 = 1000
+ assert optional_int32.get(m) == 1000
+
+ optional_msg = msgdef.lookup "optional_msg"
+ assert optional_msg.subtype == TestMessage2.descriptor
+
+ optional_msg.set(m, optional_msg.subtype.msgclass.new)
+
+ assert msgdef.msgclass == TestMessage
+
+ optional_enum = msgdef.lookup "optional_enum"
+ assert optional_enum.subtype == TestEnum.descriptor
+ assert optional_enum.subtype.class == Google::Protobuf::EnumDescriptor
+ optional_enum.subtype.each do |k, v|
+ # set with integer, check resolution to symbolic name
+ optional_enum.set(m, v)
+ assert optional_enum.get(m) == k
+ end
+ end
+
+ def test_json
+ m = TestMessage.new(:optional_int32 => 1234,
+ :optional_int64 => -0x1_0000_0000,
+ :optional_uint32 => 0x8000_0000,
+ :optional_uint64 => 0xffff_ffff_ffff_ffff,
+ :optional_bool => true,
+ :optional_float => 1.0,
+ :optional_double => -1e100,
+ :optional_string => "Test string",
+ :optional_bytes => ["FFFFFFFF"].pack('H*'),
+ :optional_msg => TestMessage2.new(:foo => 42),
+ :repeated_int32 => [1, 2, 3, 4],
+ :repeated_string => ["a", "b", "c"],
+ :repeated_bool => [true, false, true, false],
+ :repeated_msg => [TestMessage2.new(:foo => 1),
+ TestMessage2.new(:foo => 2)])
+
+ json_text = TestMessage.encode_json(m)
+ m2 = TestMessage.decode_json(json_text)
+ assert m == m2
+ end
+ end
+end
diff --git a/ruby/tests/stress.rb b/ruby/tests/stress.rb
new file mode 100644
index 00000000..cc4bbf5c
--- /dev/null
+++ b/ruby/tests/stress.rb
@@ -0,0 +1,38 @@
+#!/usr/bin/ruby
+
+require 'protobuf'
+require 'test/unit'
+
+module StressTest
+ pool = Google::Protobuf::DescriptorPool.new
+ pool.build do
+ add_message "TestMessage" do
+ optional :a, :int32, 1
+ repeated :b, :message, 2, "M"
+ end
+ add_message "M" do
+ optional :foo, :string, 1
+ end
+ end
+
+ TestMessage = pool.lookup("TestMessage").msgclass
+ M = pool.lookup("M").msgclass
+
+ class StressTest < Test::Unit::TestCase
+ def get_msg
+ TestMessage.new(:a => 1000,
+ :b => [M.new(:foo => "hello"),
+ M.new(:foo => "world")])
+ end
+ def test_stress
+ m = get_msg
+ data = TestMessage.encode(m)
+ 100_000.times do
+ mnew = TestMessage.decode(data)
+ mnew = mnew.dup
+ assert mnew.inspect == m.inspect
+ assert TestMessage.encode(mnew) == data
+ end
+ end
+ end
+end
diff --git a/src/Makefile.am b/src/Makefile.am
index b88e32ea..46190713 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -111,7 +111,7 @@ nobase_include_HEADERS = \
lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS)
-libprotobuf_lite_la_LDFLAGS = -version-info 9:2:0 -export-dynamic -no-undefined
+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 \
@@ -126,7 +126,6 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/arenastring.cc \
google/protobuf/extension_set.cc \
google/protobuf/generated_message_util.cc \
- google/protobuf/map_field.cc \
google/protobuf/message_lite.cc \
google/protobuf/repeated_field.cc \
google/protobuf/wire_format_lite.cc \
@@ -136,7 +135,7 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/io/zero_copy_stream_impl_lite.cc
libprotobuf_la_LIBADD = $(PTHREAD_LIBS)
-libprotobuf_la_LDFLAGS = -version-info 9:2:0 -export-dynamic -no-undefined
+libprotobuf_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined
libprotobuf_la_SOURCES = \
$(libprotobuf_lite_la_SOURCES) \
google/protobuf/stubs/strutil.cc \
@@ -150,6 +149,7 @@ libprotobuf_la_SOURCES = \
google/protobuf/dynamic_message.cc \
google/protobuf/extension_set_heavy.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 \
@@ -166,7 +166,7 @@ libprotobuf_la_SOURCES = \
google/protobuf/compiler/parser.cc
libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
-libprotoc_la_LDFLAGS = -version-info 9:2:0 -export-dynamic -no-undefined
+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 \
@@ -260,7 +260,8 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/javanano/javanano_message_field.cc \
google/protobuf/compiler/javanano/javanano_message.h \
google/protobuf/compiler/javanano/javanano_primitive_field.cc \
- google/protobuf/compiler/python/python_generator.cc
+ google/protobuf/compiler/python/python_generator.cc \
+ google/protobuf/compiler/ruby/ruby_generator.cc
bin_PROGRAMS = protoc
protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 1cb6441e..18536781 100644
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -38,7 +38,14 @@ namespace google {
namespace protobuf {
google::protobuf::internal::SequenceNumber Arena::lifecycle_id_generator_;
-__thread Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
+#ifdef 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(const ArenaOptions& options) {
lifecycle_id_ = lifecycle_id_generator_.GetNext();
@@ -130,18 +137,18 @@ void* Arena::AllocateAligned(size_t n) {
// 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) {
+ 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);
+ 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_;
+ void* me = &thread_cache();
Block* b = reinterpret_cast<Block*>(google::protobuf::internal::Acquire_Load(&hint_));
if (!b || b->owner != me || b->avail() < n) {
// If the next block to allocate from is the first block, try to claim it
@@ -169,7 +176,7 @@ void* Arena::AllocFromBlock(Block* b, size_t n) {
}
void* Arena::SlowAlloc(size_t n) {
- void* me = &thread_cache_;
+ 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) {
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 519e3569..d0cb163c 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -312,7 +312,12 @@ class LIBPROTOBUF_EXPORT Arena {
static const size_t kHeaderSize = sizeof(Block);
static google::protobuf::internal::SequenceNumber lifecycle_id_generator_;
- static __thread ThreadCache thread_cache_;
+#ifdef PROTOBUF_USE_DLLS
+ 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 Type. This is mainly to
// skip proto2/proto1 message objects with cc_enable_arenas=true from being
@@ -434,8 +439,8 @@ class LIBPROTOBUF_EXPORT Arena {
void CleanupList();
inline void SetThreadCacheBlock(Block* block) {
- thread_cache_.last_block_used_ = block;
- thread_cache_.last_lifecycle_id_seen = lifecycle_id_;
+ thread_cache().last_block_used_ = block;
+ thread_cache().last_lifecycle_id_seen = lifecycle_id_;
}
int64 lifecycle_id_; // Unique for each arena. Changes on Reset().
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 76a4274f..9d3d3e3e 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -128,7 +128,7 @@ TEST(ArenaTest, InitialBlockTooSmall) {
// initial block.
std::vector<char> arena_block(64);
ArenaOptions options;
- options.initial_block = arena_block.data();
+ options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
@@ -137,7 +137,7 @@ TEST(ArenaTest, InitialBlockTooSmall) {
// 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.data());
+ 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);
@@ -771,7 +771,7 @@ 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.data();
+ options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
@@ -898,7 +898,7 @@ 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.data();
+ options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
@@ -918,7 +918,7 @@ TEST(ArenaTest, NoHeapAllocationsTest) {
TEST(ArenaTest, MessageLiteOnArena) {
std::vector<char> arena_block(128 * 1024);
ArenaOptions options;
- options.initial_block = arena_block.data();
+ options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena(options);
const google::protobuf::MessageLite* prototype = dynamic_cast<
@@ -977,7 +977,7 @@ TEST(ArenaTest, SpaceUsed) {
// Test with initial block.
std::vector<char> arena_block(1024);
- options.initial_block = arena_block.data();
+ options.initial_block = &arena_block[0];
options.initial_block_size = arena_block.size();
Arena arena_2(options);
EXPECT_EQ(1024, arena_2.SpaceUsed());
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index 50f13837..d829ed91 100755
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -31,7 +31,6 @@
#ifndef GOOGLE_PROTOBUF_ARENASTRING_H__
#define GOOGLE_PROTOBUF_ARENASTRING_H__
-#include <stdint.h>
#include <string>
#include <google/protobuf/stubs/common.h>
@@ -54,7 +53,7 @@ namespace google {
namespace protobuf {
namespace internal {
-struct ArenaStringPtr {
+struct LIBPROTOBUF_EXPORT ArenaStringPtr {
inline void Set(const ::std::string* default_value,
const ::std::string& value, ::google::protobuf::Arena* arena) {
if (ptr_ == default_value) {
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index f4606c8d..dbaaa405 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -725,7 +725,7 @@ TEST_F(CommandLineInterfaceTest, ColonDelimitedPath) {
#endif
Run("protocol_compiler --test_out=$tmpdir "
- "--proto_path=$tmpdir/a"PATH_SEPARATOR"$tmpdir/b foo.proto");
+ "--proto_path=$tmpdir/a" PATH_SEPARATOR "$tmpdir/b foo.proto");
#undef PATH_SEPARATOR
diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc
index 212bc3e9..e71d35fa 100644
--- a/src/google/protobuf/compiler/cpp/cpp_message.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_message.cc
@@ -1226,7 +1226,7 @@ GenerateDescriptorDeclarations(io::Printer* printer) {
for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
printer->Print(" ");
- if (IsStringOrMessage(field)) {
+ if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
printer->Print("const ");
}
field_generators_.get(field).GeneratePrivateMembers(printer);
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index a7f95044..04ed08c9 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -613,8 +613,7 @@ GenerateSwappingCode(io::Printer* printer) const {
void StringOneofFieldGenerator::
GenerateConstructorCode(io::Printer* printer) const {
printer->Print(variables_,
- " const_cast< ::google::protobuf::internal::ArenaStringPtr*>("
- "&$classname$_default_oneof_instance_->$name$_)->UnsafeSetDefault("
+ " $classname$_default_oneof_instance_->$name$_.UnsafeSetDefault("
"$default_variable$);\n");
}
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index 20fcfa62..2a04b293 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -153,6 +153,7 @@ TEST(GeneratedMessageTest, Defaults) {
&message.optional_import_message());
}
+#ifndef PROTOBUF_USE_DLLS
TEST(GeneratedMessageTest, Int32StringConversion) {
EXPECT_EQ("971", Int32ToString(971));
EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min));
@@ -165,6 +166,7 @@ TEST(GeneratedMessageTest, Int64StringConversion) {
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 =
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 9f2127bb..931b8fa3 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -35,7 +35,7 @@
#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>
int main(int argc, char* argv[]) {
@@ -63,5 +63,10 @@ int main(int argc, char* argv[]) {
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.");
+
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 45f95df1..638a83b9 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -379,35 +379,35 @@ TEST_F(ParseMessageTest, FieldDefaults) {
#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" }"
+ " 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
}
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index 35a0a899..ad017005 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
-#if GOOGLE_PROTOBUF_VERSION < 2006000
+#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 2006002 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#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.
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 00000000..82ccd72b
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -0,0 +1,313 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <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(uint32_t 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(uint32_t 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->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32: return "int32";
+ case FieldDescriptor::CPPTYPE_INT64: return "int64";
+ case FieldDescriptor::CPPTYPE_UINT32: return "uint32";
+ case FieldDescriptor::CPPTYPE_UINT64: return "uint64";
+ case FieldDescriptor::CPPTYPE_DOUBLE: return "double";
+ case FieldDescriptor::CPPTYPE_FLOAT: return "float";
+ case FieldDescriptor::CPPTYPE_BOOL: return "bool";
+ case FieldDescriptor::CPPTYPE_ENUM: return "enum";
+ case FieldDescriptor::CPPTYPE_STRING: return "string";
+ case FieldDescriptor::CPPTYPE_MESSAGE: return "message";
+ default: assert(false); return "";
+ }
+}
+
+void GenerateMessage(const google::protobuf::Descriptor* message,
+ google::protobuf::io::Printer* printer) {
+ 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);
+ 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");
+ }
+ }
+
+ 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) {
+ 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 '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 {
+ 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 00000000..48dbefd1
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -0,0 +1,57 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#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 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/descriptor.cc b/src/google/protobuf/descriptor.cc
index 19d49cab..b8dd198d 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -345,6 +345,10 @@ 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");
@@ -354,6 +358,7 @@ void InitAllowedProto3Extendee() {
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.
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index 6bb5c6a6..cda25982 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -8,12 +8,12 @@
#include <google/protobuf/stubs/common.h>
-#if GOOGLE_PROTOBUF_VERSION < 2006000
+#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 2006002 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#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.
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index 44277fa8..2ceb41e5 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -5883,8 +5883,8 @@ class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
const Message *message,
ErrorLocation location,
const string &error_message) {
- GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << ": "
- << error_message;
+ GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
+ << element_name << "]: " << error_message;
}
private:
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index f6ae3e52..6d8a9d03 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -110,7 +110,7 @@ class Map {
~Map() { clear(); }
// Iterators
- class LIBPROTOBUF_EXPORT const_iterator
+ class const_iterator
: public std::iterator<std::forward_iterator_tag, value_type, ptrdiff_t,
const value_type*, const value_type&> {
typedef typename hash_map<Key, value_type*>::const_iterator InnerIt;
@@ -139,7 +139,7 @@ class Map {
InnerIt it_;
};
- class LIBPROTOBUF_EXPORT iterator : public std::iterator<std::forward_iterator_tag, value_type> {
+ class iterator : public std::iterator<std::forward_iterator_tag, value_type> {
typedef typename hash_map<Key, value_type*>::iterator InnerIt;
public:
@@ -302,7 +302,7 @@ class Map {
template <typename K, typename V, FieldDescriptor::Type KeyProto,
FieldDescriptor::Type ValueProto, int default_enum>
- friend class LIBPROTOBUF_EXPORT internal::MapField;
+ friend class internal::MapField;
};
} // namespace protobuf
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 6971c763..217b15f6 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -43,6 +43,10 @@ class Arena;
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 {
@@ -80,7 +84,7 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message {
// Moreover, default_enum_value is used to initialize enum field in proto2.
template <typename Key, typename Value, FieldDescriptor::Type KeyProtoType,
FieldDescriptor::Type ValueProtoType, int default_enum_value>
-class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
+class MapEntry : public MapEntryBase {
// Handlers for key/value's proto field type. Used to infer internal layout
// and provide parsing/serialization support.
typedef MapProtoTypeHandler<KeyProtoType> KeyProtoHandler;
@@ -317,6 +321,7 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
entry->reflection_ = reflection;
entry->default_instance_ = entry;
entry->InitAsDefaultInstance();
+ RegisterMapEntryDefaultInstance(entry);
return entry;
}
@@ -358,7 +363,7 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
template <typename KeyNested, typename ValueNested,
FieldDescriptor::Type KeyProtoNested,
FieldDescriptor::Type ValueProtoNested, int default_enum>
- class LIBPROTOBUF_EXPORT MapEntryWrapper
+ class MapEntryWrapper
: public MapEntry<KeyNested, ValueNested, KeyProtoNested,
ValueProtoNested, default_enum> {
typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
@@ -389,7 +394,7 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
template <typename KeyNested, typename ValueNested,
FieldDescriptor::Type KeyProtoNested,
FieldDescriptor::Type ValueProtoNested, int default_enum>
- class LIBPROTOBUF_EXPORT MapEnumEntryWrapper
+ class MapEnumEntryWrapper
: public MapEntry<KeyNested, ValueNested, KeyProtoNested,
ValueProtoNested, default_enum> {
typedef MapEntry<KeyNested, ValueNested, KeyProtoNested, ValueProtoNested,
@@ -428,7 +433,7 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase {
template <typename K, typename V,
FieldDescriptor::Type KType,
FieldDescriptor::Type VType, int default_enum>
- friend class LIBPROTOBUF_EXPORT internal::MapField;
+ friend class internal::MapField;
friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection;
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index 74431628..b535ec28 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -30,10 +30,37 @@
#include <google/protobuf/map_field.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) {
+ 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) delete repeated_field_;
}
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 0fad1351..8516d74e 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -137,7 +137,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase {
template<typename Key, typename T,
FieldDescriptor::Type KeyProto,
FieldDescriptor::Type ValueProto, int default_enum_value = 0>
-class LIBPROTOBUF_EXPORT MapField : public MapFieldBase {
+class MapField : public MapFieldBase {
// Handlers for key/value's proto field type.
typedef MapProtoTypeHandler<KeyProto> KeyProtoHandler;
typedef MapProtoTypeHandler<ValueProto> ValueProtoHandler;
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 98551839..045f8f2c 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -430,41 +430,6 @@ TEST_P(MapFieldStateTest, MutableMapField) {
}
}
-class MapFieldBaseStateStub : public MapFieldBaseStub {
- public:
- MapFieldBaseStateStub(Mutex* mutex, int* clean_counter,
- int* completed_counter)
- : mutex_(mutex),
- clean_counter_(clean_counter),
- completed_counter_(completed_counter) {}
- ~MapFieldBaseStateStub() {}
-
- protected:
- void SyncRepeatedFieldWithMapNoLock() const { Clean(); }
- void SyncMapWithRepeatedFieldNoLock() const { Clean(); }
-
- private:
- void Clean() const {
- {
- MutexLock lock(mutex_);
- ++(*clean_counter_);
- }
- struct timespec tm;
- tm.tv_sec = 0;
- tm.tv_nsec = 100000000; // 100ms
- nanosleep(&tm, NULL);
- {
- MutexLock lock(mutex_);
- // No other thread should have completed while this one was initializing.
- EXPECT_EQ(0, *completed_counter_);
- }
- }
- Mutex* mutex_;
- int* clean_counter_;
- int* completed_counter_;
-};
-
-
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index c680ccb2..9db67523 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -190,6 +190,7 @@ TEST_F(MapImplTest, MutableAt) {
ExpectSingleElement(key, value2);
}
+#ifdef PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
EXPECT_DEATH(map_.at(0), "");
}
@@ -197,6 +198,7 @@ TEST_F(MapImplTest, MutableAtNonExistDeathTest) {
TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) {
EXPECT_DEATH(const_map_.at(0), "");
}
+#endif // PROTOBUF_HAS_DEATH_TEST
TEST_F(MapImplTest, CountNonExist) {
EXPECT_EQ(0, map_.count(0));
diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc
index b27c8f19..eb7ea511 100644
--- a/src/google/protobuf/map_test_util.cc
+++ b/src/google/protobuf/map_test_util.cc
@@ -1020,7 +1020,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_int32_key_);
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_int32_int32_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1034,7 +1034,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int64_int64_key_);
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_int64_int64_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1048,7 +1048,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_uint32_uint32_key_);
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_uint32_uint32_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1062,7 +1062,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_uint64_uint64_key_);
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_uint64_uint64_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1076,7 +1076,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_sint32_sint32_key_);
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sint32_sint32_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1090,7 +1090,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_sint64_sint64_key_);
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sint64_sint64_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1104,7 +1104,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_fixed32_fixed32_key_);
uint32 val = sub_message->GetReflection()->GetUInt32(
*sub_message, map_fixed32_fixed32_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1118,7 +1118,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_fixed64_fixed64_key_);
uint64 val = sub_message->GetReflection()->GetUInt64(
*sub_message, map_fixed64_fixed64_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1132,7 +1132,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_sfixed32_sfixed32_key_);
int32 val = sub_message->GetReflection()->GetInt32(
*sub_message, map_sfixed32_sfixed32_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1146,7 +1146,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_sfixed64_sfixed64_key_);
int64 val = sub_message->GetReflection()->GetInt64(
*sub_message, map_sfixed64_sfixed64_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1160,7 +1160,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_float_key_);
float val = sub_message->GetReflection()->GetFloat(
*sub_message, map_int32_float_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1174,7 +1174,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_double_key_);
double val = sub_message->GetReflection()->GetDouble(
*sub_message, map_int32_double_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1188,7 +1188,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_bool_bool_key_);
bool val = sub_message->GetReflection()->GetBool(
*sub_message, map_bool_bool_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1202,7 +1202,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_string_string_key_);
string val = sub_message->GetReflection()->GetString(
*sub_message, map_string_string_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1216,7 +1216,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_bytes_key_);
string val = sub_message->GetReflection()->GetString(
*sub_message, map_int32_bytes_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1230,7 +1230,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_enum_key_);
const EnumValueDescriptor* val = sub_message->GetReflection()->GetEnum(
*sub_message, map_int32_enum_val_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
{
@@ -1246,7 +1246,7 @@ void MapTestUtil::MapReflectionTester::ExpectMapFieldsSetViaReflection(
*sub_message, map_int32_foreign_message_val_);
int32 val = foreign_message.GetReflection()->GetInt32(
foreign_message, foreign_c_);
- EXPECT_EQ(map.at(key), val);
+ EXPECT_EQ(map[key], val);
}
}
}
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 1d8f2499..a200bc92 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -967,6 +967,7 @@ 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;
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 33e9ea10..816e52ca 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -200,6 +200,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
EXPECT_TRUE(enum_value != NULL);
r->AddEnum(&message, repeated_field, enum_value);
+#ifdef PROTOBUF_HAS_DEATH_TEST
// Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
// remain consistent with proto2 generated code.
EXPECT_DEBUG_DEATH({
@@ -214,6 +215,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
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) {
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index e14dcc62..4798eeda 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -236,10 +236,11 @@ class RepeatedField {
Arena* arena;
Element elements[1];
};
- // Why not sizeof(Rep) - sizeof(Element)? Because this is not accurate w.r.t.
- // trailing padding on the struct -- e.g. if Element is int, this would yield
- // 12 on x86-64, not 8 as we want.
- static const size_t kRepHeaderSize = sizeof(Arena*);
+ // 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_;
@@ -263,6 +264,10 @@ class RepeatedField {
}
};
+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;
diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h
index 42f7be20..44d14d5b 100644
--- a/src/google/protobuf/repeated_field_reflection.h
+++ b/src/google/protobuf/repeated_field_reflection.h
@@ -38,6 +38,8 @@
#include <google/protobuf/stubs/shared_ptr.h>
#endif
+#include <google/protobuf/generated_enum_reflection.h>
+
namespace google {
namespace protobuf {
namespace internal {
@@ -273,7 +275,7 @@ struct RefTypeTraits<
template<typename T>
struct RefTypeTraits<
- T, typename internal::enable_if<internal::is_enum<T>::value>::type> {
+ 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.
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index ae43dfab..8b821806 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -196,8 +196,7 @@ void TestRepeatedFieldRefIterator(
int index = 0;
for (typename Ref::const_iterator it = handle.begin();
it != handle.end(); ++it) {
- ValueType value = static_cast<ValueType>(*it);
- EXPECT_EQ((message.*GetFunc)(index), value);
+ EXPECT_EQ((message.*GetFunc)(index), *it);
++index;
}
EXPECT_EQ(handle.size(), index);
@@ -410,6 +409,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
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");
@@ -419,6 +419,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) {
message, fd_repeated_int32), "");
EXPECT_DEATH(refl->GetRepeatedFieldRef<TestAllTypes>(
message, fd_repeated_foreign_message), "");
+#endif // PROTOBUF_HAS_DEATH_TEST
}
TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) {
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index 9942af50..15c0c93e 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -92,8 +92,8 @@ TEST(RepeatedField, Small) {
EXPECT_TRUE(field.empty());
EXPECT_EQ(field.size(), 0);
- // Additional 8 bytes are for 'struct Rep' header.
- int expected_usage = 4 * sizeof(int) + 8;
+ // Additional bytes are for 'struct Rep' header.
+ int expected_usage = 4 * sizeof(int) + sizeof(Arena*);
EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage);
}
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index c0cfd414..c3f735a2 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -113,24 +113,24 @@ namespace internal {
// The current version, represented as a single integer to make comparison
// easier: major * 10^6 + minor * 10^3 + micro
-#define GOOGLE_PROTOBUF_VERSION 2006002
+#define GOOGLE_PROTOBUF_VERSION 3000000
// The minimum library version which works with the current version of the
// headers.
-#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 2006000
+#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 = 2006000;
+static const int kMinHeaderVersionForLibrary = 3000000;
// The minimum protoc version which works with the current version of the
// headers.
-#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 2006000
+#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 = 2006000;
+static const int kMinHeaderVersionForProtoc = 3000000;
// Verifies that the headers and libraries are compatible. Use the macro
// below to call this.
@@ -314,6 +314,12 @@ inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) {
}
#endif
+#if defined(_MSC_VER)
+#define GOOGLE_THREAD_LOCAL __declspec(thread)
+#else
+#define GOOGLE_THREAD_LOCAL __thread
+#endif
+
// ===================================================================
// from google3/base/basictypes.h
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index 7eb4e317..5f458e98 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -95,9 +95,9 @@ TEST(LoggingTest, DefaultLogging) {
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",
+ "[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);
}
@@ -128,10 +128,10 @@ TEST(LoggingTest, CaptureLogging) {
ASSERT_EQ(2, captured_messages_.size());
EXPECT_EQ(
- "2 "__FILE__":" + SimpleItoa(start_line + 1) + ": An error.",
+ "2 " __FILE__ ":" + SimpleItoa(start_line + 1) + ": An error.",
captured_messages_[0]);
EXPECT_EQ(
- "1 "__FILE__":" + SimpleItoa(start_line + 2) + ": A warning.",
+ "1 " __FILE__ ":" + SimpleItoa(start_line + 2) + ": A warning.",
captured_messages_[1]);
}
@@ -154,10 +154,10 @@ TEST(LoggingTest, SilenceLogging) {
ASSERT_EQ(2, captured_messages_.size());
EXPECT_EQ(
- "0 "__FILE__":" + SimpleItoa(line1) + ": Visible1",
+ "0 " __FILE__ ":" + SimpleItoa(line1) + ": Visible1",
captured_messages_[0]);
EXPECT_EQ(
- "0 "__FILE__":" + SimpleItoa(line2) + ": Visible2",
+ "0 " __FILE__ ":" + SimpleItoa(line2) + ": Visible2",
captured_messages_[1]);
}
diff --git a/src/google/protobuf/stubs/fastmem.h b/src/google/protobuf/stubs/fastmem.h
index e553f142..763a6e60 100644
--- a/src/google/protobuf/stubs/fastmem.h
+++ b/src/google/protobuf/stubs/fastmem.h
@@ -46,7 +46,6 @@
#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_
#include <stddef.h>
-#include <stdint.h>
#include <stdio.h>
#include <string.h>
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
index f5365c38..b58cae3f 100644
--- a/src/google/protobuf/stubs/type_traits.h
+++ b/src/google/protobuf/stubs/type_traits.h
@@ -103,7 +103,7 @@ 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(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+#if !(defined(__GNUC__) && __GNUC__ <= 3)
template <class From, class To> struct is_convertible;
#endif
@@ -322,7 +322,7 @@ 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(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+#if !(defined(__GNUC__) && __GNUC__ <= 3)
namespace type_traits_internal {
// This class is an implementation detail for is_convertible, and you
@@ -339,6 +339,9 @@ struct ConvertHelper {
static small_ Test(To);
static big_ Test(...);
static From Create();
+ enum {
+ value = sizeof(Test(Create())) == sizeof(small_)
+ };
};
} // namespace type_traits_internal
@@ -346,9 +349,7 @@ struct ConvertHelper {
template <typename From, typename To>
struct is_convertible
: integral_constant<bool,
- sizeof(type_traits_internal::ConvertHelper<From, To>::Test(
- type_traits_internal::ConvertHelper<From, To>::Create()))
- == sizeof(small_)> {
+ type_traits_internal::ConvertHelper<From, To>::value> {
};
#endif
diff --git a/src/google/protobuf/stubs/type_traits_unittest.cc b/src/google/protobuf/stubs/type_traits_unittest.cc
index b42b9e83..49c10ace 100644
--- a/src/google/protobuf/stubs/type_traits_unittest.cc
+++ b/src/google/protobuf/stubs/type_traits_unittest.cc
@@ -610,7 +610,7 @@ TEST(TypeTraitsTest, TestIsSame) {
}
TEST(TypeTraitsTest, TestConvertible) {
-#if !defined(_MSC_VER) && !(defined(__GNUC__) && __GNUC__ <= 3)
+#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));
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 6bba8fc7..9b02f0b0 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -485,7 +485,7 @@ TEST_F(UnknownFieldSetTest, UnknownEnumValue) {
TEST_F(UnknownFieldSetTest, SpaceUsedExcludingSelf) {
UnknownFieldSet empty;
empty.AddVarint(1, 0);
- EXPECT_EQ(/* vector<UnknownField> */ 24 + /* sizeof(UnknownField) */ 16,
+ EXPECT_EQ(sizeof(vector<UnknownField>) + sizeof(UnknownField),
empty.SpaceUsedExcludingSelf());
}
diff --git a/upb b/upb
new file mode 160000
+Subproject 56913be6bb57f81dbbf7baf9cc9a0a2cd1a3649
diff --git a/vsprojects/extract_includes.bat b/vsprojects/extract_includes.bat
index beab8c4a..587c1a8a 100755
--- a/vsprojects/extract_includes.bat
+++ b/vsprojects/extract_includes.bat
@@ -7,44 +7,72 @@ md include\google\protobuf\compiler
md include\google\protobuf\compiler\cpp
md include\google\protobuf\compiler\java
md include\google\protobuf\compiler\python
-copy ..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h
-copy ..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
-copy ..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h
-copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
-copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
-copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
-copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
+copy ..\src\google\protobuf\arena.h include\google\protobuf\arena.h
+copy ..\src\google\protobuf\arenastring.h include\google\protobuf\arenastring.h
+copy ..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
+copy ..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h
+copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
+copy ..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
+copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
+copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
+copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
+copy ..\src\google\protobuf\compiler\plugin.pb.h include\google\protobuf\compiler\plugin.pb.h
+copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
+copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
copy ..\src\google\protobuf\descriptor.h include\google\protobuf\descriptor.h
copy ..\src\google\protobuf\descriptor.pb.h include\google\protobuf\descriptor.pb.h
-copy ..\src\google\protobuf\descriptor_database.h include\google\protobuf\descriptor_database.h
copy ..\src\google\protobuf\dynamic_message.h include\google\protobuf\dynamic_message.h
copy ..\src\google\protobuf\extension_set.h include\google\protobuf\extension_set.h
copy ..\src\google\protobuf\generated_enum_reflection.h include\google\protobuf\generated_enum_reflection.h
-copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
copy ..\src\google\protobuf\generated_message_reflection.h include\google\protobuf\generated_message_reflection.h
+copy ..\src\google\protobuf\generated_message_util.h include\google\protobuf\generated_message_util.h
+copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
+copy ..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h
+copy ..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h
+copy ..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h
+copy ..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h
+copy ..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h
+copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
+copy ..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
+copy ..\src\google\protobuf\map_entry.h include\google\protobuf\map_entry.h
+copy ..\src\google\protobuf\map_field.h include\google\protobuf\map_field.h
+copy ..\src\google\protobuf\map_field_inl.h include\google\protobuf\map_field_inl.h
+copy ..\src\google\protobuf\map.h include\google\protobuf\map.h
+copy ..\src\google\protobuf\map_type_handler.h include\google\protobuf\map_type_handler.h
copy ..\src\google\protobuf\message.h include\google\protobuf\message.h
copy ..\src\google\protobuf\message_lite.h include\google\protobuf\message_lite.h
+copy ..\src\google\protobuf\metadata.h include\google\protobuf\metadata.h
+copy ..\src\google\protobuf\reflection.h include\google\protobuf\reflection.h
copy ..\src\google\protobuf\reflection_ops.h include\google\protobuf\reflection_ops.h
copy ..\src\google\protobuf\repeated_field.h include\google\protobuf\repeated_field.h
+copy ..\src\google\protobuf\repeated_field_reflection.h include\google\protobuf\repeated_field_reflection.h
copy ..\src\google\protobuf\service.h include\google\protobuf\service.h
+copy ..\src\google\protobuf\stubs\atomicops.h include\google\protobuf\stubs\atomicops.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_aix.h include\google\protobuf\stubs\atomicops_internals_aix.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_arm64_gcc.h include\google\protobuf\stubs\atomicops_internals_arm64_gcc.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_arm_gcc.h include\google\protobuf\stubs\atomicops_internals_arm_gcc.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_arm_qnx.h include\google\protobuf\stubs\atomicops_internals_arm_qnx.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_atomicword_compat.h include\google\protobuf\stubs\atomicops_internals_atomicword_compat.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_generic_gcc.h include\google\protobuf\stubs\atomicops_internals_generic_gcc.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_macosx.h include\google\protobuf\stubs\atomicops_internals_macosx.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_mips_gcc.h include\google\protobuf\stubs\atomicops_internals_mips_gcc.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_pnacl.h include\google\protobuf\stubs\atomicops_internals_pnacl.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_solaris.h include\google\protobuf\stubs\atomicops_internals_solaris.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_tsan.h include\google\protobuf\stubs\atomicops_internals_tsan.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.h include\google\protobuf\stubs\atomicops_internals_x86_gcc.h
+copy ..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.h include\google\protobuf\stubs\atomicops_internals_x86_msvc.h
+copy ..\src\google\protobuf\stubs\atomic_sequence_num.h include\google\protobuf\stubs\atomic_sequence_num.h
+copy ..\src\google\protobuf\stubs\casts.h include\google\protobuf\stubs\casts.h
+copy ..\src\google\protobuf\stubs\common.h include\google\protobuf\stubs\common.h
+copy ..\src\google\protobuf\stubs\fastmem.h include\google\protobuf\stubs\fastmem.h
+copy ..\src\google\protobuf\stubs\once.h include\google\protobuf\stubs\once.h
+copy ..\src\google\protobuf\stubs\platform_macros.h include\google\protobuf\stubs\platform_macros.h
+copy ..\src\google\protobuf\stubs\singleton.h include\google\protobuf\stubs\singleton.h
+copy ..\src\google\protobuf\stubs\stl_util.h include\google\protobuf\stubs\stl_util.h
+copy ..\src\google\protobuf\stubs\template_util.h include\google\protobuf\stubs\template_util.h
+copy ..\src\google\protobuf\stubs\type_traits.h include\google\protobuf\stubs\type_traits.h
copy ..\src\google\protobuf\text_format.h include\google\protobuf\text_format.h
copy ..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h
copy ..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h
copy ..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h
copy ..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h
-copy ..\src\google\protobuf\io\coded_stream.h include\google\protobuf\io\coded_stream.h
-copy ..\src\google\protobuf\io\gzip_stream.h include\google\protobuf\io\gzip_stream.h
-copy ..\src\google\protobuf\io\printer.h include\google\protobuf\io\printer.h
-copy ..\src\google\protobuf\io\strtod.h include\google\protobuf\io\strtod.h
-copy ..\src\google\protobuf\io\tokenizer.h include\google\protobuf\io\tokenizer.h
-copy ..\src\google\protobuf\io\zero_copy_stream.h include\google\protobuf\io\zero_copy_stream.h
-copy ..\src\google\protobuf\io\zero_copy_stream_impl.h include\google\protobuf\io\zero_copy_stream_impl.h
-copy ..\src\google\protobuf\io\zero_copy_stream_impl_lite.h include\google\protobuf\io\zero_copy_stream_impl_lite.h
-copy ..\src\google\protobuf\compiler\code_generator.h include\google\protobuf\compiler\code_generator.h
-copy ..\src\google\protobuf\compiler\command_line_interface.h include\google\protobuf\compiler\command_line_interface.h
-copy ..\src\google\protobuf\compiler\importer.h include\google\protobuf\compiler\importer.h
-copy ..\src\google\protobuf\compiler\parser.h include\google\protobuf\compiler\parser.h
-copy ..\src\google\protobuf\compiler\cpp\cpp_generator.h include\google\protobuf\compiler\cpp\cpp_generator.h
-copy ..\src\google\protobuf\compiler\java\java_generator.h include\google\protobuf\compiler\java\java_generator.h
-copy ..\src\google\protobuf\compiler\python\python_generator.h include\google\protobuf\compiler\python\python_generator.h
-copy ..\src\google\protobuf\compiler\plugin.h include\google\protobuf\compiler\plugin.h
diff --git a/vsprojects/libprotobuf-lite.vcproj b/vsprojects/libprotobuf-lite.vcproj
index 06b15988..09eca4d8 100644
--- a/vsprojects/libprotobuf-lite.vcproj
+++ b/vsprojects/libprotobuf-lite.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -81,7 +81,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -248,7 +248,11 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
- RelativePath="..\src\google\protobuf\io\coded_stream.cc"
+ RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"
>
</File>
<File
@@ -256,23 +260,31 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\extension_set.cc"
+ RelativePath="..\src\google\protobuf\stubs\once.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\generated_message_util.cc"
+ RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\message_lite.cc"
+ RelativePath="..\src\google\protobuf\arena.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\once.cc"
+ RelativePath="..\src\google\protobuf\arenastring.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"
+ RelativePath="..\src\google\protobuf\extension_set.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\generated_message_util.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\message_lite.cc"
>
</File>
<File
@@ -284,15 +296,15 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
+ RelativePath="..\src\google\protobuf\io\coded_stream.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
>
</File>
</Filter>
diff --git a/vsprojects/libprotobuf.vcproj b/vsprojects/libprotobuf.vcproj
index 1a488f7d..095d3948 100644
--- a/vsprojects/libprotobuf.vcproj
+++ b/vsprojects/libprotobuf.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -81,7 +81,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -328,7 +328,11 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
- RelativePath="..\src\google\protobuf\io\coded_stream.cc"
+ RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_gcc.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"
>
</File>
<File
@@ -336,19 +340,19 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\descriptor.cc"
+ RelativePath="..\src\google\protobuf\stubs\once.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\descriptor.pb.cc"
+ RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\descriptor_database.cc"
+ RelativePath="..\src\google\protobuf\arena.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\dynamic_message.cc"
+ RelativePath="..\src\google\protobuf\arenastring.cc"
>
</File>
<File
@@ -356,83 +360,99 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\extension_set_heavy.cc"
+ RelativePath="..\src\google\protobuf\generated_message_util.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\generated_message_reflection.cc"
+ RelativePath="..\src\google\protobuf\map_field.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\generated_message_util.cc"
+ RelativePath="..\src\google\protobuf\message_lite.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\gzip_stream.cc"
+ RelativePath="..\src\google\protobuf\repeated_field.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\strtod.cc"
+ RelativePath="..\src\google\protobuf\wire_format_lite.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\importer.cc"
+ RelativePath="..\src\google\protobuf\io\coded_stream.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\message.cc"
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\message_lite.cc"
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\once.cc"
+ RelativePath="..\src\google\protobuf\stubs\strutil.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\atomicops_internals_x86_msvc.cc"
+ RelativePath="..\src\google\protobuf\stubs\strutil.h"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\parser.cc"
+ RelativePath="..\src\google\protobuf\stubs\substitute.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\printer.cc"
+ RelativePath="..\src\google\protobuf\stubs\substitute.h"
>
</File>
<File
- RelativePath="..\src\google\protobuf\reflection_ops.cc"
+ RelativePath="..\src\google\protobuf\stubs\structurally_valid.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\repeated_field.cc"
+ RelativePath="..\src\google\protobuf\descriptor.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\service.cc"
+ RelativePath="..\src\google\protobuf\descriptor_database.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\structurally_valid.cc"
+ RelativePath="..\src\google\protobuf\descriptor.pb.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\strutil.cc"
+ RelativePath="..\src\google\protobuf\dynamic_message.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\substitute.cc"
+ RelativePath="..\src\google\protobuf\extension_set_heavy.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\text_format.cc"
+ RelativePath="..\src\google\protobuf\generated_message_reflection.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\tokenizer.cc"
+ RelativePath="..\src\google\protobuf\message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\reflection_internal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\reflection_ops.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\service.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\text_format.cc"
>
</File>
<File
@@ -444,11 +464,19 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\wire_format_lite.cc"
+ RelativePath="..\src\google\protobuf\io\gzip_stream.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream.cc"
+ RelativePath="..\src\google\protobuf\io\printer.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\strtod.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\tokenizer.cc"
>
</File>
<File
@@ -456,11 +484,11 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_impl_lite.cc"
+ RelativePath="..\src\google\protobuf\compiler\importer.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\stringprintf.cc"
+ RelativePath="..\src\google\protobuf\compiler\parser.cc"
>
</File>
</Filter>
diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj
index ccbc0b36..45a5936f 100644
--- a/vsprojects/libprotoc.vcproj
+++ b/vsprojects/libprotoc.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -81,7 +81,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="4"
>
<Tool
@@ -324,22 +324,6 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.cc"
- >
- </File>
- <File
- RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
- >
- </File>
- <File
RelativePath="..\src\google\protobuf\compiler\cpp\cpp_enum.cc"
>
</File>
@@ -368,6 +352,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_map_field.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\cpp\cpp_message.cc"
>
</File>
@@ -392,6 +380,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_enum.cc"
>
</File>
@@ -428,6 +420,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\java\java_map_field.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\java\java_message.cc"
>
</File>
@@ -456,9 +452,65 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_enum_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_extension.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_generator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_helpers.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_message_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\javanano\javanano_primitive_field.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\plugin.pb.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\compiler\python\python_generator.cc"
>
</File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\subprocess.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\zip_writer.cc"
+ >
+ </File>
</Filter>
</Files>
<Globals>
diff --git a/vsprojects/lite-test.vcproj b/vsprojects/lite-test.vcproj
index 0314b36d..bb338092 100644
--- a/vsprojects/lite-test.vcproj
+++ b/vsprojects/lite-test.vcproj
@@ -19,7 +19,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
@@ -96,7 +96,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
diff --git a/vsprojects/protoc.vcproj b/vsprojects/protoc.vcproj
index 17e8474e..4359e238 100644
--- a/vsprojects/protoc.vcproj
+++ b/vsprojects/protoc.vcproj
@@ -18,7 +18,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
@@ -91,7 +91,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
diff --git a/vsprojects/readme.txt b/vsprojects/readme.txt
index 288345ad..ad342497 100644
--- a/vsprojects/readme.txt
+++ b/vsprojects/readme.txt
@@ -6,6 +6,13 @@ accessible to those who primarily work with MSVC.
Compiling and Installing
========================
+0) Check whether a gtest directory exists in the upper level directory. If
+ you checkout the code from github via "git clone", this gtest directory
+ won't exist and you won't be able to build the tests described below. To
+ avoid this problem consider downloading one of the release tar balls which
+ contains gtest already and copying the gest directory from there to your
+ protobuf directory:
+ https://github.com/google/protobuf/releases
1) Open protobuf.sln in Microsoft Visual Studio.
2) Choose "Debug" or "Release" configuration as desired.*
3) From the Build menu, choose "Build Solution". Wait for compiling to finish.
diff --git a/vsprojects/test_plugin.vcproj b/vsprojects/test_plugin.vcproj
index 2dcf2ad6..549f9503 100755
--- a/vsprojects/test_plugin.vcproj
+++ b/vsprojects/test_plugin.vcproj
@@ -19,7 +19,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
@@ -96,7 +96,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
diff --git a/vsprojects/tests.vcproj b/vsprojects/tests.vcproj
index fb815b5a..23c81f0e 100644
--- a/vsprojects/tests.vcproj
+++ b/vsprojects/tests.vcproj
@@ -19,7 +19,7 @@
<Configuration
Name="Debug|Win32"
OutputDirectory="Debug"
- IntermediateDirectory="Debug"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
@@ -96,7 +96,7 @@
<Configuration
Name="Release|Win32"
OutputDirectory="Release"
- IntermediateDirectory="Release"
+ IntermediateDirectory="$(OutDir)\$(ProjectName)"
ConfigurationType="1"
>
<Tool
@@ -247,23 +247,23 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
- RelativePath="..\src\google\protobuf\io\coded_stream_unittest.cc"
+ RelativePath="..\src\google\protobuf\arenastring_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\command_line_interface_unittest.cc"
+ RelativePath="..\src\google\protobuf\arena_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\mock_code_generator.cc"
+ RelativePath="..\src\google\protobuf\compiler\command_line_interface_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\common_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_bootstrap_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_bootstrap_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_plugin_unittest.cc"
>
</File>
<File
@@ -271,23 +271,23 @@
>
</File>
<File
- RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ RelativePath="..\src\google\protobuf\compiler\importer_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_plugin_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\java\java_plugin_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\java\java_plugin_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\mock_code_generator.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\java\java_doc_comment_unittest.cc"
+ RelativePath="..\src\google\protobuf\compiler\parser_unittest.cc"
>
</File>
<File
@@ -303,6 +303,10 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\drop_unknown_fields_test.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\dynamic_message_unittest.cc"
>
</File>
@@ -311,19 +315,35 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\testing\file.cc"
+ RelativePath="..\src\google\protobuf\generated_message_reflection_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\generated_message_reflection_unittest.cc"
+ RelativePath="..\src\google\protobuf\io\coded_stream_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\testing\googletest.cc"
+ RelativePath="..\src\google\protobuf\io\printer_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\importer_unittest.cc"
+ RelativePath="..\src\google\protobuf\io\tokenizer_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\io\zero_copy_stream_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\map_field_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\map_test.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\map_test_util.cc"
>
</File>
<File
@@ -331,15 +351,15 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\once_unittest.cc"
+ RelativePath="..\src\google\protobuf\no_field_presence_test.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\compiler\parser_unittest.cc"
+ RelativePath="..\src\google\protobuf\preserve_unknown_enum_test.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\printer_unittest.cc"
+ RelativePath="..\src\google\protobuf\proto3_arena_unittest.cc"
>
</File>
<File
@@ -347,15 +367,19 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\repeated_field_reflection_unittest.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\repeated_field_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\repeated_field_reflection_unittest.cc"
+ RelativePath="..\src\google\protobuf\stubs\common_unittest.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\structurally_valid_unittest.cc"
+ RelativePath="..\src\google\protobuf\stubs\once_unittest.cc"
>
</File>
<File
@@ -363,6 +387,14 @@
>
</File>
<File
+ RelativePath="..\src\google\protobuf\stubs\structurally_valid_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\stubs\strutil_unittest.cc"
+ >
+ </File>
+ <File
RelativePath="..\src\google\protobuf\stubs\template_util_unittest.cc"
>
</File>
@@ -371,7 +403,11 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\stubs\strutil_unittest.cc"
+ RelativePath="..\src\google\protobuf\testing\file.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\testing\googletest.cc"
>
</File>
<File
@@ -383,11 +419,31 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\tokenizer_unittest.cc"
+ RelativePath="..\src\google\protobuf\unknown_field_set_unittest.cc"
>
</File>
<File
- RelativePath=".\google\protobuf\unittest.pb.cc"
+ RelativePath="..\src\google\protobuf\wire_format_unittest.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\map_lite_unittest.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\map_proto2_unittest.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\map_unittest.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_arena.pb.cc"
>
</File>
<File
@@ -395,14 +451,30 @@
>
</File>
<File
+ RelativePath=".\google\protobuf\unittest_drop_unknown_fields.pb.cc"
+ >
+ </File>
+ <File
RelativePath=".\google\protobuf\unittest_embed_optimize_for.pb.cc"
>
</File>
<File
+ RelativePath=".\google\protobuf\unittest_empty.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_import_lite.pb.cc"
+ >
+ </File>
+ <File
RelativePath=".\google\protobuf\unittest_import.pb.cc"
>
</File>
<File
+ RelativePath=".\google\protobuf\unittest_import_public_lite.pb.cc"
+ >
+ </File>
+ <File
RelativePath=".\google\protobuf\unittest_import_public.pb.cc"
>
</File>
@@ -411,11 +483,23 @@
>
</File>
<File
+ RelativePath=".\google\protobuf\unittest_lite.pb.cc"
+ >
+ </File>
+ <File
RelativePath=".\google\protobuf\unittest_mset.pb.cc"
>
</File>
<File
- RelativePath=".\google\protobuf\unittest_optimize_for.pb.cc"
+ RelativePath=".\google\protobuf\unittest_no_arena_import.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_no_arena.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_no_field_presence.pb.cc"
>
</File>
<File
@@ -423,29 +507,33 @@
>
</File>
<File
- RelativePath="..\src\google\protobuf\unknown_field_set_unittest.cc"
+ RelativePath=".\google\protobuf\unittest_optimize_for.pb.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\wire_format_unittest.cc"
+ RelativePath=".\google\protobuf\unittest.pb.cc"
>
</File>
<File
- RelativePath="..\src\google\protobuf\io\zero_copy_stream_unittest.cc"
+ RelativePath=".\google\protobuf\unittest_preserve_unknown_enum.pb.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\google\protobuf\unittest_proto3_arena.pb.cc"
>
</File>
</Filter>
<File
- RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.proto"
+ RelativePath="..\src\google\protobuf\map_lite_unittest.proto"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ Description="Generating map_lite_unittest.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
+ Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
/>
</FileConfiguration>
<FileConfiguration
@@ -453,9 +541,57 @@
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ Description="Generating map_lite_unittest.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_lite_unittest.proto"
+ Outputs="google\protobuf\map_lite_unittest.pb.h;google\protobuf\map_lite_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\map_proto2_unittest.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_proto2_unittest.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_proto2_unittest.proto"
+ Outputs="google\protobuf\map_proto2_unittest.pb.h;google\protobuf\map_proto2_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_proto2_unittest.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_proto2_unittest.proto"
+ Outputs="google\protobuf\map_proto2_unittest.pb.h;google\protobuf\map_proto2_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\map_unittest.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_unittest.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/map_unittest.proto"
+ Outputs="google\protobuf\map_unittest.pb.h;google\protobuf\map_unittest.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating map_unittest.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/map_unittest.proto"
+ Outputs="google\protobuf\map_unittest.pb.h;google\protobuf\map_unittest.pb.cc"
/>
</FileConfiguration>
</File>
@@ -468,7 +604,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto"
Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
/>
</FileConfiguration>
@@ -478,12 +614,36 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest.proto"
Outputs="google\protobuf\unittest.pb.h;google\protobuf\unittest.pb.cc"
/>
</FileConfiguration>
</File>
<File
+ RelativePath="..\src\google\protobuf\unittest_arena.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_arena.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_arena.proto"
+ Outputs="google\protobuf\unittest_arena.pb.h;google\protobuf\unittest_arena.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_arena.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_arena.proto"
+ Outputs="google\protobuf\unittest_arena.pb.h;google\protobuf\unittest_arena.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\src\google\protobuf\unittest_custom_options.proto"
>
<FileConfiguration
@@ -492,7 +652,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_custom_options.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto"
Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
/>
</FileConfiguration>
@@ -502,12 +662,36 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_custom_options.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_custom_options.proto"
Outputs="google\protobuf\unittest_custom_options.pb.h;google\protobuf\unittest_custom_options.pb.cc"
/>
</FileConfiguration>
</File>
<File
+ RelativePath="..\src\google\protobuf\unittest_drop_unknown_fields.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_drop_unknown_fields.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_drop_unknown_fields.proto"
+ Outputs="google\protobuf\unittest_drop_unknown_fields.pb.h;google\protobuf\unittest_drop_unknown_fields.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_drop_unknown_fields.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_drop_unknown_fields.proto"
+ Outputs="google\protobuf\unittest_drop_unknown_fields.pb.h;google\protobuf\unittest_drop_unknown_fields.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\src\google\protobuf\unittest_embed_optimize_for.proto"
>
<FileConfiguration
@@ -516,7 +700,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto"
Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
/>
</FileConfiguration>
@@ -526,12 +710,60 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_embed_optimize_for.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_embed_optimize_for.proto"
Outputs="google\protobuf\unittest_embed_optimize_for.pb.h;google\protobuf\unittest_embed_optimize_for.pb.cc"
/>
</FileConfiguration>
</File>
<File
+ RelativePath="..\src\google\protobuf\unittest_empty.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_empty.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_empty.proto"
+ Outputs="google\protobuf\unittest_empty.pb.h;google\protobuf\unittest_empty.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_empty.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_empty.proto"
+ Outputs="google\protobuf\unittest_empty.pb.h;google\protobuf\unittest_empty.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_import_lite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_lite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto"
+ Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_lite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_lite.proto"
+ Outputs="google\protobuf\unittest_import_lite.pb.h;google\protobuf\unittest_import_lite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\src\google\protobuf\unittest_import.proto"
>
<FileConfiguration
@@ -540,7 +772,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_import.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto"
Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
/>
</FileConfiguration>
@@ -550,12 +782,36 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_import.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import.proto"
Outputs="google\protobuf\unittest_import.pb.h;google\protobuf\unittest_import.pb.cc"
/>
</FileConfiguration>
</File>
<File
+ RelativePath="..\src\google\protobuf\unittest_import_public_lite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_public_lite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto"
+ Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_import_public_lite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public_lite.proto"
+ Outputs="google\protobuf\unittest_import_public_lite.pb.h;google\protobuf\unittest_import_public_lite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\src\google\protobuf\unittest_import_public.proto"
>
<FileConfiguration
@@ -564,7 +820,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_import_public.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto"
Outputs="google\protobuf\unittest_import_public.pb.h;google\protobuf\unittest_import_public.pb.cc"
/>
</FileConfiguration>
@@ -574,7 +830,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_import_public.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_import_public.proto"
Outputs="google\protobuf\unittest_import_public.pb.h;google\protobuf\unittest_import_public.pb.cc"
/>
</FileConfiguration>
@@ -588,7 +844,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto"
Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
/>
</FileConfiguration>
@@ -598,12 +854,36 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_lite_imports_nonlite.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite_imports_nonlite.proto"
Outputs="google\protobuf\unittest_lite_imports_nonlite.pb.h;google\protobuf\unittest_lite_imports_nonlite.pb.cc"
/>
</FileConfiguration>
</File>
<File
+ RelativePath="..\src\google\protobuf\unittest_lite.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto"
+ Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_lite.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_lite.proto"
+ Outputs="google\protobuf\unittest_lite.pb.h;google\protobuf\unittest_lite.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
RelativePath="..\src\google\protobuf\unittest_mset.proto"
>
<FileConfiguration
@@ -612,7 +892,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_mset.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto"
Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
/>
</FileConfiguration>
@@ -622,22 +902,22 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_mset.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_mset.proto"
Outputs="google\protobuf\unittest_mset.pb.h;google\protobuf\unittest_mset.pb.cc"
/>
</FileConfiguration>
</File>
<File
- RelativePath="..\src\google\protobuf\unittest_optimize_for.proto"
+ RelativePath="..\src\google\protobuf\unittest_no_arena_import.proto"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating unittest_optimize_for.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ Description="Generating unittest_no_arena_import.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena_import.proto"
+ Outputs="google\protobuf\unittest_no_arena_import.pb.h;google\protobuf\unittest_no_arena_import.pb.cc"
/>
</FileConfiguration>
<FileConfiguration
@@ -645,9 +925,57 @@
>
<Tool
Name="VCCustomBuildTool"
- Description="Generating unittest_optimize_for.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto&#x0D;&#x0A;"
- Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ Description="Generating unittest_no_arena_import.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena_import.proto"
+ Outputs="google\protobuf\unittest_no_arena_import.pb.h;google\protobuf\unittest_no_arena_import.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_no_arena.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_no_arena.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena.proto"
+ Outputs="google\protobuf\unittest_no_arena.pb.h;google\protobuf\unittest_no_arena.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_no_arena.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_arena.proto"
+ Outputs="google\protobuf\unittest_no_arena.pb.h;google\protobuf\unittest_no_arena.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_no_field_presence.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_no_field_presence.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_field_presence.proto"
+ Outputs="google\protobuf\unittest_no_field_presence.pb.h;google\protobuf\unittest_no_field_presence.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_no_field_presence.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_field_presence.proto"
+ Outputs="google\protobuf\unittest_no_field_presence.pb.h;google\protobuf\unittest_no_field_presence.pb.cc"
/>
</FileConfiguration>
</File>
@@ -660,7 +988,7 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_no_generic_services.pb.{h,cc}..."
- CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto&#x0D;&#x0A;"
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto"
Outputs="google\protobuf\unittest_no_generic_services.pb.h;google\protobuf\unittest_no_generic_services.pb.cc"
/>
</FileConfiguration>
@@ -670,11 +998,107 @@
<Tool
Name="VCCustomBuildTool"
Description="Generating unittest_no_generic_services.pb.{h,cc}..."
- CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto&#x0D;&#x0A;"
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_no_generic_services.proto"
Outputs="google\protobuf\unittest_no_generic_services.pb.h;google\protobuf\unittest_no_generic_services.pb.cc"
/>
</FileConfiguration>
</File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_optimize_for.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_optimize_for.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto"
+ Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_optimize_for.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_optimize_for.proto"
+ Outputs="google\protobuf\unittest_optimize_for.pb.h;google\protobuf\unittest_optimize_for.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_preserve_unknown_enum.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_preserve_unknown_enum.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum.proto"
+ Outputs="google\protobuf\unittest_preserve_unknown_enum.pb.h;google\protobuf\unittest_preserve_unknown_enum.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_preserve_unknown_enum.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_preserve_unknown_enum.proto"
+ Outputs="google\protobuf\unittest_preserve_unknown_enum.pb.h;google\protobuf\unittest_preserve_unknown_enum.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\unittest_proto3_arena.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_proto3_arena.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_proto3_arena.proto"
+ Outputs="google\protobuf\unittest_proto3_arena.pb.h;google\protobuf\unittest_proto3_arena.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating unittest_proto3_arena.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/unittest_proto3_arena.proto"
+ Outputs="google\protobuf\unittest_proto3_arena.pb.h;google\protobuf\unittest_proto3_arena.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\google\protobuf\compiler\cpp\cpp_test_bad_identifiers.proto"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
+ CommandLine="Debug\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto"
+ Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCustomBuildTool"
+ Description="Generating cpp_test_bad_identifiers.pb.{h,cc}..."
+ CommandLine="Release\protoc -I../src --cpp_out=. ../src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto"
+ Outputs="google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.h;google\protobuf\compiler\cpp\cpp_test_bad_identifiers.pb.cc"
+ />
+ </FileConfiguration>
+ </File>
</Files>
<Globals>
</Globals>