Commit 63f324a9 authored by Joshua Haberman's avatar Joshua Haberman Committed by Paul Yang

Roll forward Ruby upb changes now that protobuf Ruby build is fixed (#5866)

* Rolled forward again with "Updated upb from defcleanup branch..."

Revert "Revert "Updated upb from defcleanup branch and modified Ruby to use it (#5539)" (#5848)"

This reverts commit 1568deab.

* A few more merge fixes.

* Updated for defcleanup2 branch.

* Fixed upb to define upb_decode().

* Fixed names of nested messages.

* Revert submodule.

* Set -std=gnu90 and fixed warnings/errors.

Some of our Kokoro tests seem to run with this level of warnings,
and the source strives to be gnu90 compatible.  Enforcing it for
every build removes the possibility of some errors showing up in
Kokoro/Travis tests only.

* Fixed remaining warnings with gnu90 mode.

I tried to match warning flags with what Ruby appears to do
in our Kokoro tests.

* Initialize values registered by rb_gc_register_address().

* Fixed subtle GC bug.

We need to initialize this marked value before creating the instance.

* Truly fix the GC bug.

* Updated upb for mktime() fix.

* Removed XOPEN_SOURCE as we are not using strptime().

* Removed fixed tests from the conformance failure list for Ruby.

* Fixed memory error related to oneof def names.

* Picked up new upb changes re: JSON printing.

* Uncomment concurrent decoding test.
parent 402c28a3
...@@ -67,7 +67,6 @@ module BasicTest ...@@ -67,7 +67,6 @@ module BasicTest
add_message "BadFieldNames" do add_message "BadFieldNames" do
optional :dup, :int32, 1 optional :dup, :int32, 1
optional :class, :int32, 2 optional :class, :int32, 2
optional :"a.b", :int32, 3
end end
add_message "MapMessage" do add_message "MapMessage" do
...@@ -1067,8 +1066,6 @@ module BasicTest ...@@ -1067,8 +1066,6 @@ module BasicTest
assert m['class'] == 2 assert m['class'] == 2
m['dup'] = 3 m['dup'] = 3
assert m['dup'] == 3 assert m['dup'] == 3
m['a.b'] = 4
assert m['a.b'] == 4
end end
def test_int_ranges def test_int_ranges
......
This diff is collapsed.
This diff is collapsed.
...@@ -3,11 +3,9 @@ ...@@ -3,11 +3,9 @@
require 'mkmf' require 'mkmf'
if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
# XOPEN_SOURCE needed for strptime: $CFLAGS += " -std=gnu90 -O3 -DNDEBUG -Wall -Wdeclaration-after-statement -Wsign-compare"
# https://stackoverflow.com/questions/35234152/strptime-giving-implicit-declaration-and-undefined-reference
$CFLAGS += " -std=c99 -O3 -DNDEBUG -D_XOPEN_SOURCE=700"
else else
$CFLAGS += " -std=c99 -O3 -DNDEBUG" $CFLAGS += " -std=gnu90 -O3 -DNDEBUG"
end end
......
...@@ -389,10 +389,7 @@ VALUE Map_index(VALUE _self, VALUE key) { ...@@ -389,10 +389,7 @@ VALUE Map_index(VALUE _self, VALUE key) {
* was just inserted. * was just inserted.
*/ */
VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
rb_check_frozen(_self);
Map* self = ruby_to_Map(_self); Map* self = ruby_to_Map(_self);
char keybuf[TABLE_KEY_BUF_LENGTH]; char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL; const char* keyval = NULL;
size_t length = 0; size_t length = 0;
...@@ -400,6 +397,8 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) { ...@@ -400,6 +397,8 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
void* mem; void* mem;
key = table_key(self, key, keybuf, &keyval, &length); key = table_key(self, key, keybuf, &keyval, &length);
rb_check_frozen(_self);
if (TYPE(value) == T_HASH) { if (TYPE(value) == T_HASH) {
VALUE args[1] = { value }; VALUE args[1] = { value };
value = rb_class_new_instance(1, args, self->value_type_class); value = rb_class_new_instance(1, args, self->value_type_class);
...@@ -448,16 +447,15 @@ VALUE Map_has_key(VALUE _self, VALUE key) { ...@@ -448,16 +447,15 @@ VALUE Map_has_key(VALUE _self, VALUE key) {
* nil if none was present. Throws an exception if the key is of the wrong type. * nil if none was present. Throws an exception if the key is of the wrong type.
*/ */
VALUE Map_delete(VALUE _self, VALUE key) { VALUE Map_delete(VALUE _self, VALUE key) {
rb_check_frozen(_self);
Map* self = ruby_to_Map(_self); Map* self = ruby_to_Map(_self);
char keybuf[TABLE_KEY_BUF_LENGTH]; char keybuf[TABLE_KEY_BUF_LENGTH];
const char* keyval = NULL; const char* keyval = NULL;
size_t length = 0; size_t length = 0;
upb_value v; upb_value v;
key = table_key(self, key, keybuf, &keyval, &length); key = table_key(self, key, keybuf, &keyval, &length);
rb_check_frozen(_self);
if (upb_strtable_remove2(&self->table, keyval, length, &v)) { if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
void* mem = value_memory(&v); void* mem = value_memory(&v);
return native_slot_get(self->value_type, self->value_type_class, mem); return native_slot_get(self->value_type, self->value_type_class, mem);
...@@ -473,10 +471,10 @@ VALUE Map_delete(VALUE _self, VALUE key) { ...@@ -473,10 +471,10 @@ VALUE Map_delete(VALUE _self, VALUE key) {
* Removes all entries from the map. * Removes all entries from the map.
*/ */
VALUE Map_clear(VALUE _self) { VALUE Map_clear(VALUE _self) {
rb_check_frozen(_self);
Map* self = ruby_to_Map(_self); Map* self = ruby_to_Map(_self);
rb_check_frozen(_self);
// Uninit and reinit the table -- this is faster than iterating and doing a // Uninit and reinit the table -- this is faster than iterating and doing a
// delete-lookup on each key. // delete-lookup on each key.
upb_strtable_uninit(&self->table); upb_strtable_uninit(&self->table);
......
This diff is collapsed.
...@@ -30,26 +30,10 @@ ...@@ -30,26 +30,10 @@
#include "protobuf.h" #include "protobuf.h"
// -----------------------------------------------------------------------------
// Global map from upb {msg,enum}defs to wrapper Descriptor/EnumDescriptor
// instances.
// -----------------------------------------------------------------------------
// This is a hash table from def objects (encoded by converting pointers to
// Ruby integers) to MessageDef/EnumDef instances (as Ruby values).
VALUE upb_def_to_ruby_obj_map;
VALUE cError; VALUE cError;
VALUE cParseError; VALUE cParseError;
VALUE cTypeError; VALUE cTypeError;
VALUE c_only_cookie = Qnil;
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));
}
static VALUE cached_empty_string = Qnil; static VALUE cached_empty_string = Qnil;
static VALUE cached_empty_bytes = Qnil; static VALUE cached_empty_bytes = Qnil;
...@@ -142,8 +126,8 @@ void Init_protobuf_c() { ...@@ -142,8 +126,8 @@ void Init_protobuf_c() {
kRubyStringASCIIEncoding = rb_usascii_encoding(); kRubyStringASCIIEncoding = rb_usascii_encoding();
kRubyString8bitEncoding = rb_ascii8bit_encoding(); kRubyString8bitEncoding = rb_ascii8bit_encoding();
rb_gc_register_address(&upb_def_to_ruby_obj_map); rb_gc_register_address(&c_only_cookie);
upb_def_to_ruby_obj_map = rb_hash_new(); c_only_cookie = rb_class_new_instance(0, NULL, rb_cObject);
rb_gc_register_address(&cached_empty_string); rb_gc_register_address(&cached_empty_string);
rb_gc_register_address(&cached_empty_bytes); rb_gc_register_address(&cached_empty_bytes);
......
This diff is collapsed.
...@@ -64,10 +64,11 @@ VALUE RepeatedField_subarray(VALUE _self, long beg, long len) { ...@@ -64,10 +64,11 @@ VALUE RepeatedField_subarray(VALUE _self, long beg, long len) {
int element_size = native_slot_size(self->field_type); int element_size = native_slot_size(self->field_type);
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class; VALUE field_type_class = self->field_type_class;
size_t off = beg * element_size; size_t off = beg * element_size;
VALUE ary = rb_ary_new2(len); VALUE ary = rb_ary_new2(len);
for (int i = beg; i < beg + len; i++, off += element_size) { int i;
for (i = beg; i < beg + len; i++, off += element_size) {
void* mem = ((uint8_t *)self->elements) + off; void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, field_type_class, mem); VALUE elem = native_slot_get(field_type, field_type_class, mem);
rb_ary_push(ary, elem); rb_ary_push(ary, elem);
...@@ -88,9 +89,10 @@ VALUE RepeatedField_each(VALUE _self) { ...@@ -88,9 +89,10 @@ VALUE RepeatedField_each(VALUE _self) {
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class; VALUE field_type_class = self->field_type_class;
int element_size = native_slot_size(field_type); int element_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
for (int i = 0; i < self->size; i++, off += element_size) { int i;
for (i = 0; i < self->size; i++, off += element_size) {
void* memory = (void *) (((uint8_t *)self->elements) + off); void* memory = (void *) (((uint8_t *)self->elements) + off);
VALUE val = native_slot_get(field_type, field_type_class, memory); VALUE val = native_slot_get(field_type, field_type_class, memory);
rb_yield(val); rb_yield(val);
...@@ -169,8 +171,10 @@ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) { ...@@ -169,8 +171,10 @@ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
if (index >= self->size) { if (index >= self->size) {
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
int element_size = native_slot_size(field_type); int element_size = native_slot_size(field_type);
int i;
RepeatedField_reserve(self, index + 1); RepeatedField_reserve(self, index + 1);
for (int i = self->size; i <= index; i++) { for (i = self->size; i <= index; i++) {
void* elem = RepeatedField_memoryat(self, i, element_size); void* elem = RepeatedField_memoryat(self, i, element_size);
native_slot_init(field_type, elem); native_slot_init(field_type, elem);
} }
...@@ -224,7 +228,8 @@ VALUE RepeatedField_push(VALUE _self, VALUE val) { ...@@ -224,7 +228,8 @@ VALUE RepeatedField_push(VALUE _self, VALUE val) {
} }
VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) { VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
for (int i = 0; i < RARRAY_LEN(args); i++) { int i;
for (i = 0; i < RARRAY_LEN(args); i++) {
RepeatedField_push(_self, rb_ary_entry(args, i)); RepeatedField_push(_self, rb_ary_entry(args, i));
} }
return _self; return _self;
...@@ -285,9 +290,11 @@ VALUE RepeatedField_pop_one(VALUE _self) { ...@@ -285,9 +290,11 @@ VALUE RepeatedField_pop_one(VALUE _self) {
*/ */
VALUE RepeatedField_replace(VALUE _self, VALUE list) { VALUE RepeatedField_replace(VALUE _self, VALUE list) {
RepeatedField* self = ruby_to_RepeatedField(_self); RepeatedField* self = ruby_to_RepeatedField(_self);
int i;
Check_Type(list, T_ARRAY); Check_Type(list, T_ARRAY);
self->size = 0; self->size = 0;
for (int i = 0; i < RARRAY_LEN(list); i++) { for (i = 0; i < RARRAY_LEN(list); i++) {
RepeatedField_push(_self, rb_ary_entry(list, i)); RepeatedField_push(_self, rb_ary_entry(list, i));
} }
return list; return list;
...@@ -344,8 +351,10 @@ VALUE RepeatedField_dup(VALUE _self) { ...@@ -344,8 +351,10 @@ VALUE RepeatedField_dup(VALUE _self) {
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
size_t elem_size = native_slot_size(field_type); size_t elem_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
int i;
RepeatedField_reserve(new_rptfield_self, self->size); RepeatedField_reserve(new_rptfield_self, self->size);
for (int i = 0; i < self->size; i++, off += elem_size) { for (i = 0; i < self->size; i++, off += elem_size) {
void* to_mem = (uint8_t *)new_rptfield_self->elements + off; void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
void* from_mem = (uint8_t *)self->elements + off; void* from_mem = (uint8_t *)self->elements + off;
native_slot_dup(field_type, to_mem, from_mem); native_slot_dup(field_type, to_mem, from_mem);
...@@ -363,8 +372,10 @@ VALUE RepeatedField_deep_copy(VALUE _self) { ...@@ -363,8 +372,10 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
size_t elem_size = native_slot_size(field_type); size_t elem_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
int i;
RepeatedField_reserve(new_rptfield_self, self->size); RepeatedField_reserve(new_rptfield_self, self->size);
for (int i = 0; i < self->size; i++, off += elem_size) { for (i = 0; i < self->size; i++, off += elem_size) {
void* to_mem = (uint8_t *)new_rptfield_self->elements + off; void* to_mem = (uint8_t *)new_rptfield_self->elements + off;
void* from_mem = (uint8_t *)self->elements + off; void* from_mem = (uint8_t *)self->elements + off;
native_slot_deep_copy(field_type, to_mem, from_mem); native_slot_deep_copy(field_type, to_mem, from_mem);
...@@ -384,11 +395,12 @@ VALUE RepeatedField_deep_copy(VALUE _self) { ...@@ -384,11 +395,12 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
VALUE RepeatedField_to_ary(VALUE _self) { VALUE RepeatedField_to_ary(VALUE _self) {
RepeatedField* self = ruby_to_RepeatedField(_self); RepeatedField* self = ruby_to_RepeatedField(_self);
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
size_t elem_size = native_slot_size(field_type); size_t elem_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
VALUE ary = rb_ary_new2(self->size); VALUE ary = rb_ary_new2(self->size);
for (int i = 0; i < self->size; i++, off += elem_size) { int i;
for (i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off; void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, self->field_type_class, mem); VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
rb_ary_push(ary, elem); rb_ary_push(ary, elem);
...@@ -434,7 +446,9 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) { ...@@ -434,7 +446,9 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
size_t elem_size = native_slot_size(field_type); size_t elem_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
for (int i = 0; i < self->size; i++, off += elem_size) { int i;
for (i = 0; i < self->size; i++, off += elem_size) {
void* self_mem = ((uint8_t *)self->elements) + off; void* self_mem = ((uint8_t *)self->elements) + off;
void* other_mem = ((uint8_t *)other->elements) + off; void* other_mem = ((uint8_t *)other->elements) + off;
if (!native_slot_eq(field_type, self_mem, other_mem)) { if (!native_slot_eq(field_type, self_mem, other_mem)) {
...@@ -459,7 +473,9 @@ VALUE RepeatedField_hash(VALUE _self) { ...@@ -459,7 +473,9 @@ VALUE RepeatedField_hash(VALUE _self) {
VALUE field_type_class = self->field_type_class; VALUE field_type_class = self->field_type_class;
size_t elem_size = native_slot_size(field_type); size_t elem_size = native_slot_size(field_type);
size_t off = 0; size_t off = 0;
for (int i = 0; i < self->size; i++, off += elem_size) { int i;
for (i = 0; i < self->size; i++, off += elem_size) {
void* mem = ((uint8_t *)self->elements) + off; void* mem = ((uint8_t *)self->elements) + off;
VALUE elem = native_slot_get(field_type, field_type_class, mem); VALUE elem = native_slot_get(field_type, field_type_class, mem);
h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0))); h = rb_hash_uint(h, NUM2LONG(rb_funcall(elem, hash_sym, 0)));
...@@ -481,7 +497,8 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) { ...@@ -481,7 +497,8 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
VALUE dupped = RepeatedField_dup(_self); VALUE dupped = RepeatedField_dup(_self);
if (TYPE(list) == T_ARRAY) { if (TYPE(list) == T_ARRAY) {
for (int i = 0; i < RARRAY_LEN(list); i++) { int i;
for (i = 0; i < RARRAY_LEN(list); i++) {
VALUE elem = rb_ary_entry(list, i); VALUE elem = rb_ary_entry(list, i);
RepeatedField_push(dupped, elem); RepeatedField_push(dupped, elem);
} }
...@@ -489,12 +506,14 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) { ...@@ -489,12 +506,14 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
RTYPEDDATA_TYPE(list) == &RepeatedField_type) { RTYPEDDATA_TYPE(list) == &RepeatedField_type) {
RepeatedField* self = ruby_to_RepeatedField(_self); RepeatedField* self = ruby_to_RepeatedField(_self);
RepeatedField* list_rptfield = ruby_to_RepeatedField(list); RepeatedField* list_rptfield = ruby_to_RepeatedField(list);
int i;
if (self->field_type != list_rptfield->field_type || if (self->field_type != list_rptfield->field_type ||
self->field_type_class != list_rptfield->field_type_class) { self->field_type_class != list_rptfield->field_type_class) {
rb_raise(rb_eArgError, rb_raise(rb_eArgError,
"Attempt to append RepeatedField with different element type."); "Attempt to append RepeatedField with different element type.");
} }
for (int i = 0; i < list_rptfield->size; i++) { for (i = 0; i < list_rptfield->size; i++) {
void* mem = RepeatedField_index_native(list, i); void* mem = RepeatedField_index_native(list, i);
RepeatedField_push_native(dupped, mem); RepeatedField_push_native(dupped, mem);
} }
...@@ -512,8 +531,10 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) { ...@@ -512,8 +531,10 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
* concats the passed in array to self. Returns a Ruby array. * concats the passed in array to self. Returns a Ruby array.
*/ */
VALUE RepeatedField_concat(VALUE _self, VALUE list) { VALUE RepeatedField_concat(VALUE _self, VALUE list) {
int i;
Check_Type(list, T_ARRAY); Check_Type(list, T_ARRAY);
for (int i = 0; i < RARRAY_LEN(list); i++) { for (i = 0; i < RARRAY_LEN(list); i++) {
RepeatedField_push(_self, rb_ary_entry(list, i)); RepeatedField_push(_self, rb_ary_entry(list, i));
} }
return _self; return _self;
...@@ -574,10 +595,12 @@ void RepeatedField_init_args(int argc, VALUE* argv, ...@@ -574,10 +595,12 @@ void RepeatedField_init_args(int argc, VALUE* argv,
} }
if (ary != Qnil) { if (ary != Qnil) {
int i;
if (!RB_TYPE_P(ary, T_ARRAY)) { if (!RB_TYPE_P(ary, T_ARRAY)) {
rb_raise(rb_eArgError, "Expected array as initialize argument"); rb_raise(rb_eArgError, "Expected array as initialize argument");
} }
for (int i = 0; i < RARRAY_LEN(ary); i++) { for (i = 0; i < RARRAY_LEN(ary); i++) {
RepeatedField_push(_self, rb_ary_entry(ary, i)); RepeatedField_push(_self, rb_ary_entry(ary, i));
} }
} }
...@@ -589,8 +612,10 @@ void RepeatedField_mark(void* _self) { ...@@ -589,8 +612,10 @@ void RepeatedField_mark(void* _self) {
RepeatedField* self = (RepeatedField*)_self; RepeatedField* self = (RepeatedField*)_self;
upb_fieldtype_t field_type = self->field_type; upb_fieldtype_t field_type = self->field_type;
int element_size = native_slot_size(field_type); int element_size = native_slot_size(field_type);
int i;
rb_gc_mark(self->field_type_class); rb_gc_mark(self->field_type_class);
for (int i = 0; i < self->size; i++) { for (i = 0; i < self->size; i++) {
void* memory = (((uint8_t *)self->elements) + i * element_size); void* memory = (((uint8_t *)self->elements) + i * element_size);
native_slot_mark(self->field_type, memory); native_slot_mark(self->field_type, memory);
} }
......
...@@ -181,32 +181,43 @@ void native_slot_set_value_and_case(const char* name, ...@@ -181,32 +181,43 @@ void native_slot_set_value_and_case(const char* name,
value = Qnil; value = Qnil;
} else if (CLASS_OF(value) != type_class) { } else if (CLASS_OF(value) != type_class) {
// check for possible implicit conversions // check for possible implicit conversions
VALUE converted_value = NULL; VALUE converted_value = Qnil;
char* field_type_name = rb_class2name(type_class); const char* field_type_name = rb_class2name(type_class);
if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 && if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
rb_obj_is_kind_of(value, rb_cTime)) { rb_obj_is_kind_of(value, rb_cTime)) {
// Time -> Google::Protobuf::Timestamp // Time -> Google::Protobuf::Timestamp
VALUE hash = rb_hash_new(); VALUE hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0)); rb_hash_aset(hash, rb_str_new2("seconds"),
rb_hash_aset(hash, rb_str_new2("nanos"), rb_funcall(value, rb_intern("nsec"), 0)); rb_funcall(value, rb_intern("to_i"), 0));
VALUE args[1] = { hash }; rb_hash_aset(hash, rb_str_new2("nanos"),
rb_funcall(value, rb_intern("nsec"), 0));
{
VALUE args[1] = {hash};
converted_value = rb_class_new_instance(1, args, type_class); converted_value = rb_class_new_instance(1, args, type_class);
}
} else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 && } else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
rb_obj_is_kind_of(value, rb_cNumeric)) { rb_obj_is_kind_of(value, rb_cNumeric)) {
// Numeric -> Google::Protobuf::Duration // Numeric -> Google::Protobuf::Duration
VALUE hash = rb_hash_new(); VALUE hash = rb_hash_new();
rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0)); rb_hash_aset(hash, rb_str_new2("seconds"),
VALUE n_value = rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1)); rb_funcall(value, rb_intern("to_i"), 0));
n_value = rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000)); {
VALUE n_value =
rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
n_value =
rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
n_value = rb_funcall(n_value, rb_intern("round"), 0); n_value = rb_funcall(n_value, rb_intern("round"), 0);
rb_hash_aset(hash, rb_str_new2("nanos"), n_value); rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
}
{
VALUE args[1] = { hash }; VALUE args[1] = { hash };
converted_value = rb_class_new_instance(1, args, type_class); converted_value = rb_class_new_instance(1, args, type_class);
} }
}
// raise if no suitable conversaion could be found // raise if no suitable conversaion could be found
if (converted_value == NULL) { if (converted_value == Qnil) {
rb_raise(cTypeError, rb_raise(cTypeError,
"Invalid type %s to assign to submessage field '%s'.", "Invalid type %s to assign to submessage field '%s'.",
rb_class2name(CLASS_OF(value)), name); rb_class2name(CLASS_OF(value)), name);
...@@ -462,16 +473,18 @@ static size_t align_up_to(size_t offset, size_t granularity) { ...@@ -462,16 +473,18 @@ static size_t align_up_to(size_t offset, size_t granularity) {
return (offset + granularity - 1) & ~(granularity - 1); return (offset + granularity - 1) & ~(granularity - 1);
} }
MessageLayout* create_layout(const upb_msgdef* msgdef) { MessageLayout* create_layout(const Descriptor* desc) {
const upb_msgdef *msgdef = desc->msgdef;
MessageLayout* layout = ALLOC(MessageLayout); MessageLayout* layout = ALLOC(MessageLayout);
int nfields = upb_msgdef_numfields(msgdef); int nfields = upb_msgdef_numfields(msgdef);
upb_msg_field_iter it; upb_msg_field_iter it;
upb_msg_oneof_iter oit; upb_msg_oneof_iter oit;
size_t off = 0; size_t off = 0;
size_t hasbit = 0;
layout->desc = desc;
layout->fields = ALLOC_N(MessageField, nfields); layout->fields = ALLOC_N(MessageField, nfields);
size_t hasbit = 0;
for (upb_msg_field_begin(&it, msgdef); for (upb_msg_field_begin(&it, msgdef);
!upb_msg_field_done(&it); !upb_msg_field_done(&it);
upb_msg_field_next(&it)) { upb_msg_field_next(&it)) {
...@@ -569,28 +582,25 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) { ...@@ -569,28 +582,25 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
} }
layout->size = off; layout->size = off;
layout->msgdef = msgdef; layout->msgdef = msgdef;
upb_msgdef_ref(layout->msgdef, &layout->msgdef);
return layout; return layout;
} }
void free_layout(MessageLayout* layout) { void free_layout(MessageLayout* layout) {
xfree(layout->fields); xfree(layout->fields);
upb_msgdef_unref(layout->msgdef, &layout->msgdef);
xfree(layout); xfree(layout);
} }
VALUE field_type_class(const upb_fielddef* field) { VALUE field_type_class(const MessageLayout* layout, const upb_fielddef* field) {
VALUE type_class = Qnil; VALUE type_class = Qnil;
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) { if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
VALUE submsgdesc = VALUE submsgdesc = get_msgdef_obj(layout->desc->descriptor_pool,
get_def_obj(upb_fielddef_subdef(field)); upb_fielddef_msgsubdef(field));
type_class = Descriptor_msgclass(submsgdesc); type_class = Descriptor_msgclass(submsgdesc);
} else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) { } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
VALUE subenumdesc = VALUE subenumdesc = get_enumdef_obj(layout->desc->descriptor_pool,
get_def_obj(upb_fielddef_subdef(field)); upb_fielddef_enumsubdef(field));
type_class = EnumDescriptor_enummodule(subenumdesc); type_class = EnumDescriptor_enummodule(subenumdesc);
} }
return type_class; return type_class;
...@@ -664,7 +674,7 @@ void layout_clear(MessageLayout* layout, ...@@ -664,7 +674,7 @@ void layout_clear(MessageLayout* layout,
const upb_fielddef* key_field = map_field_key(field); const upb_fielddef* key_field = map_field_key(field);
const upb_fielddef* value_field = map_field_value(field); const upb_fielddef* value_field = map_field_value(field);
VALUE type_class = field_type_class(value_field); VALUE type_class = field_type_class(layout, value_field);
if (type_class != Qnil) { if (type_class != Qnil) {
VALUE args[3] = { VALUE args[3] = {
...@@ -685,7 +695,7 @@ void layout_clear(MessageLayout* layout, ...@@ -685,7 +695,7 @@ void layout_clear(MessageLayout* layout,
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
VALUE ary = Qnil; VALUE ary = Qnil;
VALUE type_class = field_type_class(field); VALUE type_class = field_type_class(layout, field);
if (type_class != Qnil) { if (type_class != Qnil) {
VALUE args[2] = { VALUE args[2] = {
...@@ -700,9 +710,9 @@ void layout_clear(MessageLayout* layout, ...@@ -700,9 +710,9 @@ void layout_clear(MessageLayout* layout,
DEREF(memory, VALUE) = ary; DEREF(memory, VALUE) = ary;
} else { } else {
native_slot_set(upb_fielddef_name(field), native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
upb_fielddef_type(field), field_type_class(field), field_type_class(layout, field), memory,
memory, layout_get_default(field)); layout_get_default(field));
} }
} }
...@@ -756,20 +766,19 @@ VALUE layout_get(MessageLayout* layout, ...@@ -756,20 +766,19 @@ VALUE layout_get(MessageLayout* layout,
return layout_get_default(field); return layout_get_default(field);
} }
return native_slot_get(upb_fielddef_type(field), return native_slot_get(upb_fielddef_type(field),
field_type_class(field), field_type_class(layout, field), memory);
memory);
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
return *((VALUE *)memory); return *((VALUE *)memory);
} else if (!field_set) { } else if (!field_set) {
return layout_get_default(field); return layout_get_default(field);
} else { } else {
return native_slot_get(upb_fielddef_type(field), return native_slot_get(upb_fielddef_type(field),
field_type_class(field), field_type_class(layout, field), memory);
memory);
} }
} }
static void check_repeated_field_type(VALUE val, const upb_fielddef* field) { static void check_repeated_field_type(const MessageLayout* layout, VALUE val,
const upb_fielddef* field) {
RepeatedField* self; RepeatedField* self;
assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED); assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
...@@ -783,25 +792,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) { ...@@ -783,25 +792,13 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
rb_raise(cTypeError, "Repeated field array has wrong element type"); rb_raise(cTypeError, "Repeated field array has wrong element type");
} }
if (self->field_type == UPB_TYPE_MESSAGE) { if (self->field_type_class != field_type_class(layout, field)) {
if (self->field_type_class != rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
rb_raise(cTypeError,
"Repeated field array has wrong message class");
}
}
if (self->field_type == UPB_TYPE_ENUM) {
if (self->field_type_class !=
EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
rb_raise(cTypeError,
"Repeated field array has wrong enum class");
}
} }
} }
static void check_map_field_type(VALUE val, const upb_fielddef* field) { static void check_map_field_type(const MessageLayout* layout, VALUE val,
const upb_fielddef* field) {
const upb_fielddef* key_field = map_field_key(field); const upb_fielddef* key_field = map_field_key(field);
const upb_fielddef* value_field = map_field_value(field); const upb_fielddef* value_field = map_field_value(field);
Map* self; Map* self;
...@@ -818,17 +815,11 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) { ...@@ -818,17 +815,11 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
if (self->value_type != upb_fielddef_type(value_field)) { if (self->value_type != upb_fielddef_type(value_field)) {
rb_raise(cTypeError, "Map value type does not match field's value type"); rb_raise(cTypeError, "Map value type does not match field's value type");
} }
if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE || if (self->value_type_class != field_type_class(layout, value_field)) {
upb_fielddef_type(value_field) == UPB_TYPE_ENUM) { rb_raise(cTypeError, "Map value type has wrong message/enum class");
if (self->value_type_class !=
get_def_obj(upb_fielddef_subdef(value_field))) {
rb_raise(cTypeError,
"Map value type has wrong message/enum class");
}
} }
} }
void layout_set(MessageLayout* layout, void layout_set(MessageLayout* layout,
void* storage, void* storage,
const upb_fielddef* field, const upb_fielddef* field,
...@@ -856,20 +847,19 @@ void layout_set(MessageLayout* layout, ...@@ -856,20 +847,19 @@ void layout_set(MessageLayout* layout,
// and case number are altered atomically (w.r.t. the Ruby VM). // and case number are altered atomically (w.r.t. the Ruby VM).
native_slot_set_value_and_case( native_slot_set_value_and_case(
upb_fielddef_name(field), upb_fielddef_name(field),
upb_fielddef_type(field), field_type_class(field), upb_fielddef_type(field), field_type_class(layout, field),
memory, val, memory, val,
oneof_case, upb_fielddef_number(field)); oneof_case, upb_fielddef_number(field));
} }
} else if (is_map_field(field)) { } else if (is_map_field(field)) {
check_map_field_type(val, field); check_map_field_type(layout, val, field);
DEREF(memory, VALUE) = val; DEREF(memory, VALUE) = val;
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) { } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
check_repeated_field_type(val, field); check_repeated_field_type(layout, val, field);
DEREF(memory, VALUE) = val; DEREF(memory, VALUE) = val;
} else { } else {
native_slot_set(upb_fielddef_name(field), native_slot_set(upb_fielddef_name(field), upb_fielddef_type(field),
upb_fielddef_type(field), field_type_class(field), field_type_class(layout, field), memory, val);
memory, val);
} }
if (layout->fields[upb_fielddef_index(field)].hasbit != if (layout->fields[upb_fielddef_index(field)].hasbit !=
......
This diff is collapsed.
This diff is collapsed.
...@@ -50,6 +50,72 @@ else ...@@ -50,6 +50,72 @@ else
rescue LoadError rescue LoadError
require 'google/protobuf_c' require 'google/protobuf_c'
end end
module Google
module Protobuf
module Internal
def self.infer_package(names)
# Package is longest common prefix ending in '.', if any.
min, max = names.minmax
last_common_dot = nil
min.size.times { |i|
if min[i] != max[i] then break end
if min[i] == ?. then last_common_dot = i end
}
if last_common_dot
return min.slice(0, last_common_dot)
end
end
class NestingBuilder
def initialize(msg_names, enum_names)
@to_pos = {nil=>nil}
@msg_children = Hash.new { |hash, key| hash[key] = [] }
@enum_children = Hash.new { |hash, key| hash[key] = [] }
msg_names.each_with_index { |name, idx| @to_pos[name] = idx }
enum_names.each_with_index { |name, idx| @to_pos[name] = idx }
msg_names.each { |name| @msg_children[parent(name)] << name }
enum_names.each { |name| @enum_children[parent(name)] << name }
end
def build(package)
return build_msg(package)
end
private
def build_msg(msg)
return {
:pos => @to_pos[msg],
:msgs => @msg_children[msg].map { |child| build_msg(child) },
:enums => @enum_children[msg].map { |child| @to_pos[child] },
}
end
private
def parent(name)
idx = name.rindex(?.)
if idx
return name.slice(0, idx)
else
return nil
end
end
end
def self.fixup_descriptor(package, msg_names, enum_names)
if package.nil?
package = self.infer_package(msg_names + enum_names)
end
nesting = NestingBuilder.new(msg_names, enum_names).build(package)
return package, nesting
end
end
end
end
end end
require 'google/protobuf/repeated_field' require 'google/protobuf/repeated_field'
......
...@@ -17,7 +17,6 @@ module BasicTest ...@@ -17,7 +17,6 @@ module BasicTest
add_message "BadFieldNames" do add_message "BadFieldNames" do
optional :dup, :int32, 1 optional :dup, :int32, 1
optional :class, :int32, 2 optional :class, :int32, 2
optional :"a.b", :int32, 3
end end
end end
...@@ -285,6 +284,14 @@ module BasicTest ...@@ -285,6 +284,14 @@ module BasicTest
assert_match(/No such field: not_in_message/, e.message) assert_match(/No such field: not_in_message/, e.message)
end end
#def test_json_quoted_string
# m = TestMessage.decode_json(%q(
# "optionalInt64": "1",,
# }))
# puts(m)
# assert_equal 1, m.optional_int32
#end
def test_to_h def test_to_h
m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)]) m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
expected_result = { expected_result = {
...@@ -371,11 +378,6 @@ module BasicTest ...@@ -371,11 +378,6 @@ module BasicTest
assert nil != file_descriptor assert nil != file_descriptor
assert_equal "tests/basic_test.proto", file_descriptor.name assert_equal "tests/basic_test.proto", file_descriptor.name
assert_equal :proto3, file_descriptor.syntax assert_equal :proto3, file_descriptor.syntax
file_descriptor = BadFieldNames.descriptor.file_descriptor
assert nil != file_descriptor
assert_equal nil, file_descriptor.name
assert_equal :proto3, file_descriptor.syntax
end end
# Ruby 2.5 changed to raise FrozenError instead of RuntimeError # Ruby 2.5 changed to raise FrozenError instead of RuntimeError
......
...@@ -18,7 +18,6 @@ module BasicTestProto2 ...@@ -18,7 +18,6 @@ module BasicTestProto2
add_message "BadFieldNames" do add_message "BadFieldNames" do
optional :dup, :int32, 1 optional :dup, :int32, 1
optional :class, :int32, 2 optional :class, :int32, 2
optional :"a.b", :int32, 3
end end
end end
end end
......
...@@ -807,7 +807,7 @@ module CommonTests ...@@ -807,7 +807,7 @@ module CommonTests
proto_module::TestMessage2.new(:foo => 2)]) proto_module::TestMessage2.new(:foo => 2)])
data = proto_module::TestMessage.encode m data = proto_module::TestMessage.encode m
m2 = proto_module::TestMessage.decode data m2 = proto_module::TestMessage.decode data
assert m == m2 assert_equal m, m2
data = Google::Protobuf.encode m data = Google::Protobuf.encode m
m2 = Google::Protobuf.decode(proto_module::TestMessage, data) m2 = Google::Protobuf.decode(proto_module::TestMessage, data)
...@@ -902,8 +902,6 @@ module CommonTests ...@@ -902,8 +902,6 @@ module CommonTests
assert m['class'] == 2 assert m['class'] == 2
m['dup'] = 3 m['dup'] = 3
assert m['dup'] == 3 assert m['dup'] == 3
m['a.b'] = 4
assert m['a.b'] == 4
end end
def test_int_ranges def test_int_ranges
...@@ -1084,9 +1082,7 @@ module CommonTests ...@@ -1084,9 +1082,7 @@ module CommonTests
json_text = proto_module::TestMessage.encode_json(m) json_text = proto_module::TestMessage.encode_json(m)
m2 = proto_module::TestMessage.decode_json(json_text) m2 = proto_module::TestMessage.decode_json(json_text)
puts m.inspect assert_equal m, m2
puts m2.inspect
assert m == m2
# Crash case from GitHub issue 283. # Crash case from GitHub issue 283.
bar = proto_module::Bar.new(msg: "bar") bar = proto_module::Bar.new(msg: "bar")
...@@ -1132,7 +1128,7 @@ module CommonTests ...@@ -1132,7 +1128,7 @@ module CommonTests
actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
assert JSON.parse(actual, :symbolize_names => true) == expected assert_equal expected, JSON.parse(actual, :symbolize_names => true)
end end
def test_json_emit_defaults_submsg def test_json_emit_defaults_submsg
...@@ -1167,7 +1163,7 @@ module CommonTests ...@@ -1167,7 +1163,7 @@ module CommonTests
actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
assert JSON.parse(actual, :symbolize_names => true) == expected assert_equal expected, JSON.parse(actual, :symbolize_names => true)
end end
def test_json_emit_defaults_repeated_submsg def test_json_emit_defaults_repeated_submsg
...@@ -1201,7 +1197,7 @@ module CommonTests ...@@ -1201,7 +1197,7 @@ module CommonTests
actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true) actual = proto_module::TestMessage.encode_json(m, :emit_defaults => true)
assert JSON.parse(actual, :symbolize_names => true) == expected assert_equal expected, JSON.parse(actual, :symbolize_names => true)
end end
def value_from_ruby(value) def value_from_ruby(value)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment