aboutsummaryrefslogtreecommitdiffhomepage
path: root/ruby
diff options
context:
space:
mode:
Diffstat (limited to 'ruby')
-rw-r--r--ruby/Rakefile4
-rw-r--r--ruby/ext/google/protobuf_c/extconf.rb9
-rw-r--r--ruby/ext/google/protobuf_c/map.c31
-rw-r--r--ruby/ext/google/protobuf_c/message.c14
-rw-r--r--ruby/ext/google/protobuf_c/protobuf.h2
-rw-r--r--ruby/ext/google/protobuf_c/wrap_memcpy.c51
-rw-r--r--ruby/google-protobuf.gemspec8
-rw-r--r--ruby/tests/basic.rb10
8 files changed, 120 insertions, 9 deletions
diff --git a/ruby/Rakefile b/ruby/Rakefile
index 40d0a314..a329a777 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -64,13 +64,13 @@ else
task 'gem:windows' do
require 'rake_compiler_dock'
- RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0"
+ RakeCompilerDock.sh "bundle && IN_DOCKER=true rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0"
end
if RUBY_PLATFORM =~ /darwin/
task 'gem:native' do
system "rake genproto"
- system "rake cross native gem RUBY_CC_VERSION=2.3.0:2.2.2:2.1.5:2.0.0"
+ system "rake cross native gem RUBY_CC_VERSION=2.4.0:2.3.0:2.2.2:2.1.5:2.0.0"
end
else
task 'gem:native' => [:genproto, 'gem:windows']
diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb
index b368dcc6..0886e607 100644
--- a/ruby/ext/google/protobuf_c/extconf.rb
+++ b/ruby/ext/google/protobuf_c/extconf.rb
@@ -4,7 +4,14 @@ require 'mkmf'
$CFLAGS += " -std=c99 -O3 -DNDEBUG"
+
+if RUBY_PLATFORM =~ /linux/
+ # Instruct the linker to point memcpy calls at our __wrap_memcpy wrapper.
+ $LDFLAGS += " -Wl,-wrap,memcpy"
+end
+
$objs = ["protobuf.o", "defs.o", "storage.o", "message.o",
- "repeated_field.o", "map.o", "encode_decode.o", "upb.o"]
+ "repeated_field.o", "map.o", "encode_decode.o", "upb.o",
+ "wrap_memcpy.o"]
create_makefile("google/protobuf_c")
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 12f1f9dd..4be54c39 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -654,6 +654,35 @@ VALUE Map_hash(VALUE _self) {
/*
* call-seq:
+ * Map.to_h => {}
+ *
+ * Returns a Ruby Hash object containing all the values within the map
+ */
+VALUE Map_to_h(VALUE _self) {
+ Map* self = ruby_to_Map(_self);
+ VALUE hash = rb_hash_new();
+ upb_strtable_iter it;
+ for (upb_strtable_begin(&it, &self->table);
+ !upb_strtable_done(&it);
+ upb_strtable_next(&it)) {
+ VALUE key = table_key_to_ruby(
+ self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
+ upb_value v = upb_strtable_iter_value(&it);
+ void* mem = value_memory(&v);
+ VALUE value = native_slot_get(self->value_type,
+ self->value_type_class,
+ mem);
+
+ if (self->value_type == UPB_TYPE_MESSAGE) {
+ value = Message_to_h(value);
+ }
+ rb_hash_aset(hash, key, value);
+ }
+ return hash;
+}
+
+/*
+ * call-seq:
* Map.inspect => string
*
* Returns a string representing this map's elements. It will be formatted as
@@ -804,6 +833,8 @@ void Map_register(VALUE module) {
rb_define_method(klass, "dup", Map_dup, 0);
rb_define_method(klass, "==", Map_eq, 1);
rb_define_method(klass, "hash", Map_hash, 0);
+ rb_define_method(klass, "to_hash", Map_to_h, 0);
+ rb_define_method(klass, "to_h", Map_to_h, 0);
rb_define_method(klass, "inspect", Map_inspect, 0);
rb_define_method(klass, "merge", Map_merge, 1);
rb_include_module(klass, rb_mEnumerable);
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index 837a974b..29911140 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -394,7 +394,12 @@ VALUE Message_inspect(VALUE _self) {
return str;
}
-
+/*
+ * call-seq:
+ * Message.to_h => {}
+ *
+ * Returns the message as a Ruby Hash object, with keys as symbols.
+ */
VALUE Message_to_h(VALUE _self) {
MessageHeader* self;
VALUE hash;
@@ -410,8 +415,13 @@ VALUE Message_to_h(VALUE _self) {
VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
field);
VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
- if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
+ if (upb_fielddef_ismap(field)) {
+ msg_value = Map_to_h(msg_value);
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
msg_value = RepeatedField_to_ary(msg_value);
+ } else if (msg_value != Qnil &&
+ upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
+ msg_value = Message_to_h(msg_value);
}
rb_hash_aset(hash, msg_key, msg_value);
}
diff --git a/ruby/ext/google/protobuf_c/protobuf.h b/ruby/ext/google/protobuf_c/protobuf.h
index d5ced567..520e9d9b 100644
--- a/ruby/ext/google/protobuf_c/protobuf.h
+++ b/ruby/ext/google/protobuf_c/protobuf.h
@@ -424,6 +424,7 @@ VALUE Map_dup(VALUE _self);
VALUE Map_deep_copy(VALUE _self);
VALUE Map_eq(VALUE _self, VALUE _other);
VALUE Map_hash(VALUE _self);
+VALUE Map_to_h(VALUE _self);
VALUE Map_inspect(VALUE _self);
VALUE Map_merge(VALUE _self, VALUE hashmap);
VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
@@ -496,6 +497,7 @@ 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_to_h(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);
diff --git a/ruby/ext/google/protobuf_c/wrap_memcpy.c b/ruby/ext/google/protobuf_c/wrap_memcpy.c
new file mode 100644
index 00000000..394a52f9
--- /dev/null
+++ b/ruby/ext/google/protobuf_c/wrap_memcpy.c
@@ -0,0 +1,51 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc. All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string.h>
+
+// On x86-64 Linux with glibc, we link against the 2.2.5 version of memcpy so
+// that we avoid depending on the 2.14 version of the symbol. This way,
+// distributions that are using pre-2.14 versions of glibc can successfully use
+// the gem we distribute (https://github.com/google/protobuf/issues/2783).
+//
+// This wrapper is enabled by passing the linker flags -Wl,-wrap,memcpy in
+// extconf.rb.
+#ifdef __linux__
+#if defined(__x86_64__) && defined(__GNU_LIBRARY__)
+__asm__(".symver memcpy,memcpy@GLIBC_2.2.5");
+void *__wrap_memcpy(void *dest, const void *src, size_t n) {
+ return memcpy(dest, src, n);
+}
+#else
+void *__wrap_memcpy(void *dest, const void *src, size_t n) {
+ return memmove(dest, src, n);
+}
+#endif
+#endif
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index 97bf9970..836b1dd2 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -1,7 +1,7 @@
Gem::Specification.new do |s|
s.name = "google-protobuf"
- s.version = "3.2.0"
- s.licenses = ["BSD"]
+ s.version = "3.3.0"
+ s.licenses = ["BSD-3-Clause"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
s.homepage = "https://developers.google.com/protocol-buffers"
@@ -15,12 +15,12 @@ Gem::Specification.new do |s|
else
s.files += Dir.glob('ext/**/*')
s.extensions= ["ext/google/protobuf_c/extconf.rb"]
- s.add_development_dependency "rake-compiler-dock", "~> 0.5.1"
+ s.add_development_dependency "rake-compiler-dock", "~> 0.6.0"
end
s.test_files = ["tests/basic.rb",
"tests/stress.rb",
"tests/generated_code_test.rb"]
s.add_development_dependency "rake-compiler", "~> 0.9.5"
- s.add_development_dependency "test-unit", "~> 3.0.9"
+ s.add_development_dependency "test-unit", '~> 3.0', '>= 3.0.9'
s.add_development_dependency "rubygems-tasks", "~> 0.2.4"
end
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index d9df7a5a..02cc7a03 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -928,6 +928,16 @@ module BasicTest
:repeated_uint64=>[]
}
assert_equal expected_result, m.to_h
+
+ m = MapMessage.new(
+ :map_string_int32 => {"a" => 1, "b" => 2},
+ :map_string_msg => {"a" => TestMessage2.new(:foo => 1),
+ "b" => TestMessage2.new(:foo => 2)})
+ expected_result = {
+ :map_string_int32 => {"a" => 1, "b" => 2},
+ :map_string_msg => {"a" => {:foo => 1}, "b" => {:foo => 2}}
+ }
+ assert_equal expected_result, m.to_h
end