Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
P
protobuf
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
protobuf
Commits
0eb9b279
Unverified
Commit
0eb9b279
authored
Nov 07, 2019
by
Joshua Haberman
Committed by
GitHub
Nov 07, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6797 from haberman/ruby-lazy-wrappers
Ruby lazy wrappers optimization
parents
0150f7f5
781d6963
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
628 additions
and
76 deletions
+628
-76
encode_decode.c
ruby/ext/google/protobuf_c/encode_decode.c
+219
-12
map.c
ruby/ext/google/protobuf_c/map.c
+4
-2
message.c
ruby/ext/google/protobuf_c/message.c
+34
-25
protobuf.h
ruby/ext/google/protobuf_c/protobuf.h
+7
-2
repeated_field.c
ruby/ext/google/protobuf_c/repeated_field.c
+3
-2
storage.c
ruby/ext/google/protobuf_c/storage.c
+31
-10
basic.rb
ruby/tests/basic.rb
+42
-0
basic_test.proto
ruby/tests/basic_test.proto
+40
-1
basic_test_proto2.proto
ruby/tests/basic_test_proto2.proto
+28
-1
common_tests.rb
ruby/tests/common_tests.rb
+220
-21
No files found.
ruby/ext/google/protobuf_c/encode_decode.c
View file @
0eb9b279
...
...
@@ -278,6 +278,17 @@ static void *appendsubmsg_handler(void *closure, const void *hd) {
return
submsg
;
}
// Appends a wrapper to a repeated field (a regular Ruby array for now).
static
void
*
appendwrapper_handler
(
void
*
closure
,
const
void
*
hd
)
{
VALUE
ary
=
(
VALUE
)
closure
;
int
size
=
RepeatedField_size
(
ary
);
(
void
)
hd
;
RepeatedField_push
(
ary
,
Qnil
);
return
RepeatedField_index_native
(
ary
,
size
);
}
// Sets a non-repeated submessage field in a message.
static
void
*
submsg_handler
(
void
*
closure
,
const
void
*
hd
)
{
MessageHeader
*
msg
=
closure
;
...
...
@@ -298,6 +309,15 @@ static void *submsg_handler(void *closure, const void *hd) {
return
submsg
;
}
static
void
*
startwrapper
(
void
*
closure
,
const
void
*
hd
)
{
char
*
msg
=
closure
;
const
submsg_handlerdata_t
*
submsgdata
=
hd
;
set_hasbit
(
closure
,
submsgdata
->
hasbit
);
return
msg
+
submsgdata
->
ofs
;
}
// Handler data for startmap/endmap handlers.
typedef
struct
{
size_t
ofs
;
...
...
@@ -486,14 +506,39 @@ static void *oneofsubmsg_handler(void *closure,
// indicating a VALUE is present and expect a valid VALUE. See comment in
// layout_set() for more detail: basically, the change to the value and the
// case must be atomic w.r.t. the Ruby VM.
DEREF
(
msg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
DEREF
(
msg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
submsg_rb
=
DEREF
(
msg
,
oneofdata
->
ofs
,
VALUE
);
TypedData_Get_Struct
(
submsg_rb
,
MessageHeader
,
&
Message_type
,
submsg
);
return
submsg
;
}
static
void
*
oneof_startwrapper
(
void
*
closure
,
const
void
*
hd
)
{
char
*
msg
=
closure
;
const
oneof_handlerdata_t
*
oneofdata
=
hd
;
DEREF
(
msg
,
oneofdata
->
case_ofs
,
uint32_t
)
=
oneofdata
->
oneof_case_num
;
return
msg
+
oneofdata
->
ofs
;
}
bool
is_wrapper
(
const
upb_msgdef
*
m
)
{
switch
(
upb_msgdef_wellknowntype
(
m
))
{
case
UPB_WELLKNOWN_DOUBLEVALUE
:
case
UPB_WELLKNOWN_FLOATVALUE
:
case
UPB_WELLKNOWN_INT64VALUE
:
case
UPB_WELLKNOWN_UINT64VALUE
:
case
UPB_WELLKNOWN_INT32VALUE
:
case
UPB_WELLKNOWN_UINT32VALUE
:
case
UPB_WELLKNOWN_STRINGVALUE
:
case
UPB_WELLKNOWN_BYTESVALUE
:
case
UPB_WELLKNOWN_BOOLVALUE
:
return
true
;
default
:
return
false
;
}
}
// Set up handlers for a repeated field.
static
void
add_handlers_for_repeated_field
(
upb_handlers
*
h
,
const
Descriptor
*
desc
,
...
...
@@ -535,12 +580,96 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
VALUE
subklass
=
field_type_class
(
desc
->
layout
,
f
);
upb_handlerattr
attr
=
UPB_HANDLERATTR_INIT
;
attr
.
handler_data
=
newsubmsghandlerdata
(
h
,
0
,
-
1
,
subklass
);
if
(
is_wrapper
(
upb_fielddef_msgsubdef
(
f
)))
{
upb_handlers_setstartsubmsg
(
h
,
f
,
appendwrapper_handler
,
&
attr
);
}
else
{
upb_handlers_setstartsubmsg
(
h
,
f
,
appendsubmsg_handler
,
&
attr
);
}
break
;
}
}
}
static
bool
doublewrapper_handler
(
void
*
closure
,
const
void
*
hd
,
double
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
DBL2NUM
(
val
);
return
true
;
}
static
bool
floatwrapper_handler
(
void
*
closure
,
const
void
*
hd
,
float
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
DBL2NUM
(
val
);
return
true
;
}
static
bool
int64wrapper_handler
(
void
*
closure
,
const
void
*
hd
,
int64_t
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
LL2NUM
(
val
);
return
true
;
}
static
bool
uint64wrapper_handler
(
void
*
closure
,
const
void
*
hd
,
uint64_t
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
ULL2NUM
(
val
);
return
true
;
}
static
bool
int32wrapper_handler
(
void
*
closure
,
const
void
*
hd
,
int32_t
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
INT2NUM
(
val
);
return
true
;
}
static
bool
uint32wrapper_handler
(
void
*
closure
,
const
void
*
hd
,
uint32_t
val
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
UINT2NUM
(
val
);
return
true
;
}
static
void
*
startstringwrapper_handler
(
void
*
closure
,
const
void
*
hd
,
size_t
size_hint
)
{
VALUE
*
rbval
=
closure
;
(
void
)
size_hint
;
*
rbval
=
rb_str_new
(
NULL
,
0
);
rb_enc_associate
(
*
rbval
,
kRubyStringUtf8Encoding
);
return
closure
;
}
static
size_t
stringwrapper_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
ptr
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
noleak_rb_str_cat
(
*
rbval
,
ptr
,
len
);
return
len
;
}
static
void
*
startbyteswrapper_handler
(
void
*
closure
,
const
void
*
hd
,
size_t
size_hint
)
{
VALUE
*
rbval
=
closure
;
(
void
)
size_hint
;
*
rbval
=
rb_str_new
(
NULL
,
0
);
rb_enc_associate
(
*
rbval
,
kRubyString8bitEncoding
);
return
closure
;
}
static
size_t
byteswrapper_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
ptr
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
noleak_rb_str_cat
(
*
rbval
,
ptr
,
len
);
return
len
;
}
static
bool
boolwrapper_handler
(
void
*
closure
,
const
void
*
hd
,
bool
val
)
{
VALUE
*
rbval
=
closure
;
if
(
val
)
{
*
rbval
=
Qtrue
;
}
else
{
*
rbval
=
Qfalse
;
}
return
true
;
}
// Set up handlers for a singular field.
static
void
add_handlers_for_singular_field
(
const
Descriptor
*
desc
,
upb_handlers
*
h
,
...
...
@@ -580,8 +709,11 @@ static void add_handlers_for_singular_field(const Descriptor* desc,
upb_handlerattr
attr
=
UPB_HANDLERATTR_INIT
;
attr
.
handler_data
=
newsubmsghandlerdata
(
h
,
offset
,
hasbit
,
field_type_class
(
desc
->
layout
,
f
));
if
(
is_wrapper
(
upb_fielddef_msgsubdef
(
f
)))
{
upb_handlers_setstartsubmsg
(
h
,
f
,
startwrapper
,
&
attr
);
}
else
{
upb_handlers_setstartsubmsg
(
h
,
f
,
submsg_handler
,
&
attr
);
break
;
}
}
}
}
...
...
@@ -623,6 +755,45 @@ static void add_handlers_for_mapentry(const upb_msgdef* msgdef, upb_handlers* h,
MESSAGE_FIELD_NO_HASBIT
);
}
static
void
add_handlers_for_wrapper
(
const
upb_msgdef
*
msgdef
,
upb_handlers
*
h
)
{
const
upb_fielddef
*
f
=
upb_msgdef_itof
(
msgdef
,
1
);
switch
(
upb_msgdef_wellknowntype
(
msgdef
))
{
case
UPB_WELLKNOWN_DOUBLEVALUE
:
upb_handlers_setdouble
(
h
,
f
,
doublewrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_FLOATVALUE
:
upb_handlers_setfloat
(
h
,
f
,
floatwrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_INT64VALUE
:
upb_handlers_setint64
(
h
,
f
,
int64wrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_UINT64VALUE
:
upb_handlers_setuint64
(
h
,
f
,
uint64wrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_INT32VALUE
:
upb_handlers_setint32
(
h
,
f
,
int32wrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_UINT32VALUE
:
upb_handlers_setuint32
(
h
,
f
,
uint32wrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_STRINGVALUE
:
upb_handlers_setstartstr
(
h
,
f
,
startstringwrapper_handler
,
NULL
);
upb_handlers_setstring
(
h
,
f
,
stringwrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_BYTESVALUE
:
upb_handlers_setstartstr
(
h
,
f
,
startbyteswrapper_handler
,
NULL
);
upb_handlers_setstring
(
h
,
f
,
byteswrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_BOOLVALUE
:
upb_handlers_setbool
(
h
,
f
,
boolwrapper_handler
,
NULL
);
return
;
default
:
rb_raise
(
rb_eRuntimeError
,
"Internal logic error with well-known types."
);
}
}
// Set up handlers for a oneof field.
static
void
add_handlers_for_oneof_field
(
upb_handlers
*
h
,
const
upb_fielddef
*
f
,
...
...
@@ -662,7 +833,11 @@ static void add_handlers_for_oneof_field(upb_handlers *h,
break
;
}
case
UPB_TYPE_MESSAGE
:
{
if
(
is_wrapper
(
upb_fielddef_msgsubdef
(
f
)))
{
upb_handlers_setstartsubmsg
(
h
,
f
,
oneof_startwrapper
,
&
attr
);
}
else
{
upb_handlers_setstartsubmsg
(
h
,
f
,
oneofsubmsg_handler
,
&
attr
);
}
break
;
}
}
...
...
@@ -683,6 +858,10 @@ static bool unknown_field_handler(void* closure, const void* hd,
return
true
;
}
size_t
get_field_offset
(
MessageLayout
*
layout
,
const
upb_fielddef
*
f
)
{
return
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
+
sizeof
(
MessageHeader
);
}
void
add_handlers_for_message
(
const
void
*
closure
,
upb_handlers
*
h
)
{
const
VALUE
descriptor_pool
=
(
VALUE
)
closure
;
const
upb_msgdef
*
msgdef
=
upb_handlers_msgdef
(
h
);
...
...
@@ -706,6 +885,12 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) {
return
;
}
// If this is a wrapper type, use special handlers and bail.
if
(
is_wrapper
(
msgdef
))
{
add_handlers_for_wrapper
(
msgdef
,
h
);
return
;
}
upb_handlers_setunknown
(
h
,
unknown_field_handler
,
&
attr
);
for
(
upb_msg_field_begin
(
&
i
,
desc
->
msgdef
);
...
...
@@ -713,8 +898,7 @@ void add_handlers_for_message(const void *closure, upb_handlers *h) {
upb_msg_field_next
(
&
i
))
{
const
upb_fielddef
*
f
=
upb_msg_iter_field
(
&
i
);
const
upb_oneofdef
*
oneof
=
upb_fielddef_containingoneof
(
f
);
size_t
offset
=
desc
->
layout
->
fields
[
upb_fielddef_index
(
f
)].
offset
+
sizeof
(
MessageHeader
);
size_t
offset
=
get_field_offset
(
desc
->
layout
,
f
);
if
(
oneof
)
{
size_t
oneof_case_offset
=
...
...
@@ -826,17 +1010,28 @@ VALUE Message_decode(VALUE klass, VALUE data) {
{
const
upb_pbdecodermethod
*
method
=
msgdef_decodermethod
(
desc
);
const
upb_handlers
*
h
=
upb_pbdecodermethod_desthandlers
(
method
);
const
upb_msgdef
*
m
=
upb_handlers_msgdef
(
h
);
VALUE
wrapper
=
Qnil
;
void
*
ptr
=
msg
;
stackenv
se
;
upb_sink
sink
;
upb_pbdecoder
*
decoder
;
stackenv_init
(
&
se
,
"Error occurred during parsing: %"
PRIsVALUE
);
upb_sink_reset
(
&
sink
,
h
,
msg
);
if
(
is_wrapper
(
m
))
{
ptr
=
&
wrapper
;
}
upb_sink_reset
(
&
sink
,
h
,
ptr
);
decoder
=
upb_pbdecoder_create
(
se
.
arena
,
method
,
sink
,
&
se
.
status
);
upb_bufsrc_putbuf
(
RSTRING_PTR
(
data
),
RSTRING_LEN
(
data
),
upb_pbdecoder_input
(
decoder
));
stackenv_uninit
(
&
se
);
if
(
is_wrapper
(
m
))
{
msg_rb
=
ruby_wrapper_type
(
msgklass
,
wrapper
);
}
}
return
msg_rb
;
...
...
@@ -890,13 +1085,21 @@ VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
{
const
upb_json_parsermethod
*
method
=
msgdef_jsonparsermethod
(
desc
);
const
upb_handlers
*
h
=
get_fill_handlers
(
desc
);
const
upb_msgdef
*
m
=
upb_handlers_msgdef
(
h
);
stackenv
se
;
upb_sink
sink
;
upb_json_parser
*
parser
;
DescriptorPool
*
pool
=
ruby_to_DescriptorPool
(
generated_pool
);
stackenv_init
(
&
se
,
"Error occurred during parsing: %"
PRIsVALUE
);
upb_sink_reset
(
&
sink
,
get_fill_handlers
(
desc
),
msg
);
if
(
is_wrapper
(
m
))
{
rb_raise
(
rb_eRuntimeError
,
"Parsing a wrapper type from JSON at the top level does not work."
);
}
upb_sink_reset
(
&
sink
,
h
,
msg
);
parser
=
upb_json_parser_create
(
se
.
arena
,
method
,
pool
->
symtab
,
sink
,
&
se
.
status
,
RTEST
(
ignore_unknown_fields
));
upb_bufsrc_putbuf
(
RSTRING_PTR
(
data
),
RSTRING_LEN
(
data
),
...
...
@@ -969,6 +1172,7 @@ static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
upb_selector_t
sel
=
0
;
int
size
;
int
i
;
VALUE
type_class
=
ruby_to_RepeatedField
(
ary
)
->
field_type_class
;
if
(
ary
==
Qnil
)
return
;
if
(
!
emit_defaults
&&
NUM2INT
(
RepeatedField_length
(
ary
))
==
0
)
return
;
...
...
@@ -1003,9 +1207,11 @@ static void putary(VALUE ary, const upb_fielddef* f, upb_sink sink, int depth,
case
UPB_TYPE_BYTES
:
putstr
(
*
((
VALUE
*
)
memory
),
f
,
subsink
);
break
;
case
UPB_TYPE_MESSAGE
:
putsubmsg
(
*
((
VALUE
*
)
memory
),
f
,
subsink
,
depth
,
emit_defaults
,
is_json
);
case
UPB_TYPE_MESSAGE
:
{
VALUE
val
=
native_slot_get
(
UPB_TYPE_MESSAGE
,
type_class
,
memory
);
putsubmsg
(
val
,
f
,
subsink
,
depth
,
emit_defaults
,
is_json
);
break
;
}
#undef T
...
...
@@ -1306,8 +1512,10 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
putstr
(
str
,
f
,
sink
);
}
}
else
if
(
upb_fielddef_issubmsg
(
f
))
{
putsubmsg
(
DEREF
(
msg
,
offset
,
VALUE
),
f
,
sink
,
depth
,
emit_defaults
,
is_json
);
// OPT: could try to avoid the layout_get() (which will expand lazy
// wrappers).
VALUE
val
=
layout_get
(
desc
->
layout
,
Message_data
(
msg
),
f
);
putsubmsg
(
val
,
f
,
sink
,
depth
,
emit_defaults
,
is_json
);
}
else
{
upb_selector_t
sel
=
getsel
(
f
,
upb_handlers_getprimitivehandlertype
(
f
));
...
...
@@ -1341,7 +1549,6 @@ static void putmsg(VALUE msg_rb, const Descriptor* desc,
}
#undef T
}
}
...
...
ruby/ext/google/protobuf_c/map.c
View file @
0eb9b279
...
...
@@ -559,7 +559,8 @@ VALUE Map_deep_copy(VALUE _self) {
void
*
mem
=
value_memory
(
&
v
);
upb_value
dup
;
void
*
dup_mem
=
value_memory
(
&
dup
);
native_slot_deep_copy
(
self
->
value_type
,
dup_mem
,
mem
);
native_slot_deep_copy
(
self
->
value_type
,
self
->
value_type_class
,
dup_mem
,
mem
);
if
(
!
upb_strtable_insert2
(
&
new_self
->
table
,
upb_strtable_iter_key
(
&
it
),
...
...
@@ -631,7 +632,8 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
return
Qfalse
;
}
if
(
!
native_slot_eq
(
self
->
value_type
,
mem
,
other_mem
))
{
if
(
!
native_slot_eq
(
self
->
value_type
,
self
->
value_type_class
,
mem
,
other_mem
))
{
// Present, but value not equal.
return
Qfalse
;
}
...
...
ruby/ext/google/protobuf_c/message.c
View file @
0eb9b279
...
...
@@ -62,13 +62,12 @@ VALUE Message_alloc(VALUE klass) {
Descriptor
*
desc
=
ruby_to_Descriptor
(
descriptor
);
MessageHeader
*
msg
;
VALUE
ret
;
size_t
size
;
if
(
desc
->
layout
==
NULL
)
{
create_layout
(
desc
);
}
msg
=
ALLOC_N
(
uint8_t
,
sizeof
(
MessageHeader
)
+
desc
->
layout
->
size
);
msg
=
(
void
*
)
ALLOC_N
(
uint8_t
,
sizeof
(
MessageHeader
)
+
desc
->
layout
->
size
);
msg
->
descriptor
=
desc
;
msg
->
unknown_fields
=
NULL
;
memcpy
(
Message_data
(
msg
),
desc
->
layout
->
empty_template
,
desc
->
layout
->
size
);
...
...
@@ -109,30 +108,36 @@ enum {
};
// Check if the field is a well known wrapper type
static
bool
is_wrapper_type_field
(
const
MessageLayout
*
layout
,
const
upb_fielddef
*
field
)
{
const
char
*
field_type_name
=
rb_class2name
(
field_type_class
(
layout
,
field
));
return
strcmp
(
field_type_name
,
"Google::Protobuf::DoubleValue"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::FloatValue"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::Int32Value"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::Int64Value"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::UInt32Value"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::UInt64Value"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::BoolValue"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::StringValue"
)
==
0
||
strcmp
(
field_type_name
,
"Google::Protobuf::BytesValue"
)
==
0
;
bool
is_wrapper_type_field
(
const
upb_fielddef
*
field
)
{
const
upb_msgdef
*
m
;
if
(
upb_fielddef_type
(
field
)
!=
UPB_TYPE_MESSAGE
)
{
return
false
;
}
m
=
upb_fielddef_msgsubdef
(
field
);
switch
(
upb_msgdef_wellknowntype
(
m
))
{
case
UPB_WELLKNOWN_DOUBLEVALUE
:
case
UPB_WELLKNOWN_FLOATVALUE
:
case
UPB_WELLKNOWN_INT64VALUE
:
case
UPB_WELLKNOWN_UINT64VALUE
:
case
UPB_WELLKNOWN_INT32VALUE
:
case
UPB_WELLKNOWN_UINT32VALUE
:
case
UPB_WELLKNOWN_STRINGVALUE
:
case
UPB_WELLKNOWN_BYTESVALUE
:
case
UPB_WELLKNOWN_BOOLVALUE
:
return
true
;
default:
return
false
;
}
}
// Get a new Ruby wrapper type and set the initial value
static
VALUE
ruby_wrapper_type
(
const
MessageLayout
*
layout
,
const
upb_fielddef
*
field
,
const
VALUE
value
)
{
if
(
is_wrapper_type_field
(
layout
,
field
)
&&
value
!=
Qnil
)
{
VALUE
ruby_wrapper_type
(
VALUE
type_class
,
VALUE
value
)
{
if
(
value
!=
Qnil
)
{
VALUE
hash
=
rb_hash_new
();
rb_hash_aset
(
hash
,
rb_str_new2
(
"value"
),
value
);
{
VALUE
args
[
1
]
=
{
hash
};
return
rb_class_new_instance
(
1
,
args
,
field_type_class
(
layout
,
field
)
);
return
rb_class_new_instance
(
1
,
args
,
type_class
);
}
}
return
Qnil
;
...
...
@@ -193,8 +198,7 @@ static int extract_method_call(VALUE method_name, MessageHeader* self,
// Check if field exists and is a wrapper type
if
(
upb_msgdef_lookupname
(
self
->
descriptor
->
msgdef
,
wrapper_field_name
,
name_len
-
9
,
&
test_f_wrapper
,
&
test_o_wrapper
)
&&
upb_fielddef_type
(
test_f_wrapper
)
==
UPB_TYPE_MESSAGE
&&
is_wrapper_type_field
(
self
->
descriptor
->
layout
,
test_f_wrapper
))
{
is_wrapper_type_field
(
test_f_wrapper
))
{
// It does exist!
has_field
=
true
;
if
(
accessor_type
==
METHOD_SETTER
)
{
...
...
@@ -329,12 +333,17 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
return
layout_has
(
self
->
descriptor
->
layout
,
Message_data
(
self
),
f
);
}
else
if
(
accessor_type
==
METHOD_WRAPPER_GETTER
)
{
VALUE
value
=
layout_get
(
self
->
descriptor
->
layout
,
Message_data
(
self
),
f
);
if
(
value
!=
Qnil
)
{
value
=
rb_funcall
(
value
,
rb_intern
(
"value"
),
0
);
}
switch
(
TYPE
(
value
))
{
case
T_DATA
:
return
rb_funcall
(
value
,
rb_intern
(
"value"
),
0
);
case
T_NIL
:
return
Qnil
;
default:
return
value
;
}
}
else
if
(
accessor_type
==
METHOD_WRAPPER_SETTER
)
{
VALUE
wrapper
=
ruby_wrapper_type
(
self
->
descriptor
->
layout
,
f
,
argv
[
1
]);
VALUE
wrapper
=
ruby_wrapper_type
(
field_type_class
(
self
->
descriptor
->
layout
,
f
),
argv
[
1
]);
layout_set
(
self
->
descriptor
->
layout
,
Message_data
(
self
),
f
,
wrapper
);
return
Qnil
;
}
else
if
(
accessor_type
==
METHOD_ENUM_GETTER
)
{
...
...
ruby/ext/google/protobuf_c/protobuf.h
View file @
0eb9b279
...
...
@@ -363,8 +363,10 @@ VALUE native_slot_get(upb_fieldtype_t type,
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_deep_copy
(
upb_fieldtype_t
type
,
VALUE
type_class
,
void
*
to
,
void
*
from
);
bool
native_slot_eq
(
upb_fieldtype_t
type
,
VALUE
type_class
,
void
*
mem1
,
void
*
mem2
);
VALUE
native_slot_encode_and_freeze_string
(
upb_fieldtype_t
type
,
VALUE
value
);
void
native_slot_check_int_range_precision
(
const
char
*
name
,
upb_fieldtype_t
type
,
VALUE
value
);
...
...
@@ -556,6 +558,9 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2);
VALUE
layout_hash
(
MessageLayout
*
layout
,
void
*
storage
);
VALUE
layout_inspect
(
MessageLayout
*
layout
,
void
*
storage
);
bool
is_wrapper_type_field
(
const
upb_fielddef
*
field
);
VALUE
ruby_wrapper_type
(
VALUE
type_class
,
VALUE
value
);
// -----------------------------------------------------------------------------
// Message class creation.
// -----------------------------------------------------------------------------
...
...
ruby/ext/google/protobuf_c/repeated_field.c
View file @
0eb9b279
...
...
@@ -378,7 +378,7 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
for
(
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
);
native_slot_deep_copy
(
field_type
,
self
->
field_type_class
,
to_mem
,
from_mem
);
new_rptfield_self
->
size
++
;
}
...
...
@@ -451,7 +451,8 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
for
(
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
))
{
if
(
!
native_slot_eq
(
field_type
,
self
->
field_type_class
,
self_mem
,
other_mem
))
{
return
Qfalse
;
}
}
...
...
ruby/ext/google/protobuf_c/storage.c
View file @
0eb9b279
...
...
@@ -294,8 +294,20 @@ VALUE native_slot_get(upb_fieldtype_t type,
return
DEREF
(
memory
,
int8_t
)
?
Qtrue
:
Qfalse
;
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
case
UPB_TYPE_MESSAGE
:
return
DEREF
(
memory
,
VALUE
);
case
UPB_TYPE_MESSAGE
:
{
VALUE
val
=
DEREF
(
memory
,
VALUE
);
// Lazily expand wrapper type if necessary.
int
type
=
TYPE
(
val
);
if
(
type
!=
T_DATA
&&
type
!=
T_NIL
)
{
// This must be a wrapper type.
val
=
ruby_wrapper_type
(
type_class
,
val
);
DEREF
(
memory
,
VALUE
)
=
val
;
}
return
val
;
}
case
UPB_TYPE_ENUM
:
{
int32_t
val
=
DEREF
(
memory
,
int32_t
);
VALUE
symbol
=
enum_lookup
(
type_class
,
INT2NUM
(
val
));
...
...
@@ -372,7 +384,8 @@ 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
)
{
void
native_slot_deep_copy
(
upb_fieldtype_t
type
,
VALUE
type_class
,
void
*
to
,
void
*
from
)
{
switch
(
type
)
{
case
UPB_TYPE_STRING
:
case
UPB_TYPE_BYTES
:
{
...
...
@@ -382,7 +395,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
break
;
}
case
UPB_TYPE_MESSAGE
:
{
VALUE
from_val
=
DEREF
(
from
,
VALUE
);
VALUE
from_val
=
native_slot_get
(
type
,
type_class
,
from
);
DEREF
(
to
,
VALUE
)
=
(
from_val
!=
Qnil
)
?
Message_deep_copy
(
from_val
)
:
Qnil
;
break
;
...
...
@@ -392,13 +405,14 @@ 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
)
{
bool
native_slot_eq
(
upb_fieldtype_t
type
,
VALUE
type_class
,
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
val1
=
native_slot_get
(
type
,
type_class
,
mem1
);
VALUE
val2
=
native_slot_get
(
type
,
type_class
,
mem2
);
VALUE
ret
=
rb_funcall
(
val1
,
rb_intern
(
"=="
),
1
,
val2
);
return
ret
==
Qtrue
;
}
...
...
@@ -1025,7 +1039,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
if
(
slot_read_oneof_case
(
layout
,
from
,
oneof
)
==
upb_fielddef_number
(
field
))
{
*
to_oneof_case
=
*
from_oneof_case
;
native_slot_deep_copy
(
upb_fielddef_type
(
field
),
to_memory
,
from_memory
);
native_slot_deep_copy
(
upb_fielddef_type
(
field
),
field_type_class
(
layout
,
field
),
to_memory
,
from_memory
);
}
}
else
if
(
is_map_field
(
field
))
{
DEREF
(
to_memory
,
VALUE
)
=
...
...
@@ -1039,7 +1055,9 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
slot_set_hasbit
(
layout
,
to
,
field
);
}
native_slot_deep_copy
(
upb_fielddef_type
(
field
),
to_memory
,
from_memory
);
native_slot_deep_copy
(
upb_fielddef_type
(
field
),
field_type_class
(
layout
,
field
),
to_memory
,
from_memory
);
}
}
}
...
...
@@ -1061,7 +1079,8 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
if
(
*
msg1_oneof_case
!=
*
msg2_oneof_case
||
(
slot_read_oneof_case
(
layout
,
msg1
,
oneof
)
==
upb_fielddef_number
(
field
)
&&
!
native_slot_eq
(
upb_fielddef_type
(
field
),
msg1_memory
,
!
native_slot_eq
(
upb_fielddef_type
(
field
),
field_type_class
(
layout
,
field
),
msg1_memory
,
msg2_memory
)))
{
return
Qfalse
;
}
...
...
@@ -1078,7 +1097,9 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
}
else
{
if
(
slot_is_hasbit_set
(
layout
,
msg1
,
field
)
!=
slot_is_hasbit_set
(
layout
,
msg2
,
field
)
||
!
native_slot_eq
(
upb_fielddef_type
(
field
),
msg1_memory
,
msg2_memory
))
{
!
native_slot_eq
(
upb_fielddef_type
(
field
),
field_type_class
(
layout
,
field
),
msg1_memory
,
msg2_memory
))
{
return
Qfalse
;
}
}
...
...
ruby/tests/basic.rb
View file @
0eb9b279
...
...
@@ -234,6 +234,48 @@ module BasicTest
m
.
map_string_int32
[
'aaa'
]
=
3
end
def
test_map_wrappers
run_asserts
=
->
(
m
)
{
assert_equal
2.0
,
m
.
map_double
[
0
].
value
assert_equal
4.0
,
m
.
map_float
[
0
].
value
assert_equal
3
,
m
.
map_int32
[
0
].
value
assert_equal
4
,
m
.
map_int64
[
0
].
value
assert_equal
5
,
m
.
map_uint32
[
0
].
value
assert_equal
6
,
m
.
map_uint64
[
0
].
value
assert_equal
true
,
m
.
map_bool
[
0
].
value
assert_equal
'str'
,
m
.
map_string
[
0
].
value
assert_equal
'fun'
,
m
.
map_bytes
[
0
].
value
}
m
=
proto_module
::
Wrapper
.
new
(
map_double:
{
0
=>
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
)},
map_float:
{
0
=>
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
)},
map_int32:
{
0
=>
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
)},
map_int64:
{
0
=>
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
)},
map_uint32:
{
0
=>
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
)},
map_uint64:
{
0
=>
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
)},
map_bool:
{
0
=>
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
)},
map_string:
{
0
=>
Google
::
Protobuf
::
StringValue
.
new
(
value:
'str'
)},
map_bytes:
{
0
=>
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
)},
)
run_asserts
.
call
(
m
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m
)
m2
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m2
)
# Test the case where we are serializing directly from the parsed form
# (before anything lazy is materialized).
m3
=
proto_module
::
Wrapper
::
decode
(
serialized
)
serialized2
=
proto_module
::
Wrapper
::
encode
(
m3
)
m4
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
run_asserts
.
call
(
m4
)
# Test that the lazy form compares equal to the expanded form.
m5
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
assert_equal
m5
,
m
end
def
test_concurrent_decoding
o
=
Outer
.
new
o
.
items
[
0
]
=
Inner
.
new
...
...
ruby/tests/basic_test.proto
View file @
0eb9b279
...
...
@@ -126,7 +126,46 @@ message Wrapper {
google.protobuf.BytesValue
bytes
=
9
;
string
real_string
=
100
;
oneof
a_oneof
{
string
oneof_string
=
10
;
string
string_in_oneof
=
10
;
}
// Repeated wrappers don't make sense, but we still need to make sure they
// work and don't crash.
repeated
google.protobuf.DoubleValue
repeated_double
=
11
;
repeated
google.protobuf.FloatValue
repeated_float
=
12
;
repeated
google.protobuf.Int32Value
repeated_int32
=
13
;
repeated
google.protobuf.Int64Value
repeated_int64
=
14
;
repeated
google.protobuf.UInt32Value
repeated_uint32
=
15
;
repeated
google.protobuf.UInt64Value
repeated_uint64
=
16
;
repeated
google.protobuf.BoolValue
repeated_bool
=
17
;
repeated
google.protobuf.StringValue
repeated_string
=
18
;
repeated
google.protobuf.BytesValue
repeated_bytes
=
19
;
// Wrappers as map keys don't make sense, but we still need to make sure they
// work and don't crash.
map
<
int32
,
google.protobuf.DoubleValue
>
map_double
=
21
;
map
<
int32
,
google.protobuf.FloatValue
>
map_float
=
22
;
map
<
int32
,
google.protobuf.Int32Value
>
map_int32
=
23
;
map
<
int32
,
google.protobuf.Int64Value
>
map_int64
=
24
;
map
<
int32
,
google.protobuf.UInt32Value
>
map_uint32
=
25
;
map
<
int32
,
google.protobuf.UInt64Value
>
map_uint64
=
26
;
map
<
int32
,
google.protobuf.BoolValue
>
map_bool
=
27
;
map
<
int32
,
google.protobuf.StringValue
>
map_string
=
28
;
map
<
int32
,
google.protobuf.BytesValue
>
map_bytes
=
29
;
// Wrappers in oneofs don't make sense, but we still need to make sure they
// work and don't crash.
oneof
wrapper_oneof
{
google.protobuf.DoubleValue
oneof_double
=
31
;
google.protobuf.FloatValue
oneof_float
=
32
;
google.protobuf.Int32Value
oneof_int32
=
33
;
google.protobuf.Int64Value
oneof_int64
=
34
;
google.protobuf.UInt32Value
oneof_uint32
=
35
;
google.protobuf.UInt64Value
oneof_uint64
=
36
;
google.protobuf.BoolValue
oneof_bool
=
37
;
google.protobuf.StringValue
oneof_string
=
38
;
google.protobuf.BytesValue
oneof_bytes
=
39
;
string
oneof_plain_string
=
101
;
}
}
...
...
ruby/tests/basic_test_proto2.proto
View file @
0eb9b279
...
...
@@ -133,7 +133,34 @@ message Wrapper {
optional
google.protobuf.BytesValue
bytes
=
9
;
optional
string
real_string
=
100
;
oneof
a_oneof
{
string
oneof_string
=
10
;
string
string_in_oneof
=
10
;
}
// Repeated wrappers don't really make sense, but we still need to make sure
// they work and don't crash.
repeated
google.protobuf.DoubleValue
repeated_double
=
11
;
repeated
google.protobuf.FloatValue
repeated_float
=
12
;
repeated
google.protobuf.Int32Value
repeated_int32
=
13
;
repeated
google.protobuf.Int64Value
repeated_int64
=
14
;
repeated
google.protobuf.UInt32Value
repeated_uint32
=
15
;
repeated
google.protobuf.UInt64Value
repeated_uint64
=
16
;
repeated
google.protobuf.BoolValue
repeated_bool
=
17
;
repeated
google.protobuf.StringValue
repeated_string
=
18
;
repeated
google.protobuf.BytesValue
repeated_bytes
=
19
;
// Wrappers in oneofs don't make sense, but we still need to make sure they
// work and don't crash.
oneof
wrapper_oneof
{
google.protobuf.DoubleValue
oneof_double
=
31
;
google.protobuf.FloatValue
oneof_float
=
32
;
google.protobuf.Int32Value
oneof_int32
=
33
;
google.protobuf.Int64Value
oneof_int64
=
34
;
google.protobuf.UInt32Value
oneof_uint32
=
35
;
google.protobuf.UInt64Value
oneof_uint64
=
36
;
google.protobuf.BoolValue
oneof_bool
=
37
;
google.protobuf.StringValue
oneof_string
=
38
;
google.protobuf.BytesValue
oneof_bytes
=
39
;
string
oneof_plain_string
=
101
;
}
}
...
...
ruby/tests/common_tests.rb
View file @
0eb9b279
...
...
@@ -1266,42 +1266,197 @@ module CommonTests
end
def
test_wrapper_getters
m
=
proto_module
::
Wrapper
.
new
(
double:
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
),
float:
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
),
int32:
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
),
int64:
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
),
uint32:
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
),
uint64:
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
),
bool:
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
),
string:
Google
::
Protobuf
::
StringValue
.
new
(
value:
'str'
),
bytes:
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
),
real_string:
'100'
)
run_asserts
=
->
(
m
)
{
assert_equal
2.0
,
m
.
double_as_value
assert_equal
2.0
,
m
.
double
.
value
assert_equal
2.0
,
m
.
double_as_value
assert_equal
4.0
,
m
.
float_as_value
assert_equal
4.0
,
m
.
float
.
value
assert_equal
4.0
,
m
.
float_as_value
assert_equal
3
,
m
.
int32_as_value
assert_equal
3
,
m
.
int32
.
value
assert_equal
3
,
m
.
int32_as_value
assert_equal
4
,
m
.
int64_as_value
assert_equal
4
,
m
.
int64
.
value
assert_equal
4
,
m
.
int64_as_value
assert_equal
5
,
m
.
uint32_as_value
assert_equal
5
,
m
.
uint32
.
value
assert_equal
5
,
m
.
uint32_as_value
assert_equal
6
,
m
.
uint64_as_value
assert_equal
6
,
m
.
uint64
.
value
assert_equal
6
,
m
.
uint64_as_value
assert_equal
true
,
m
.
bool_as_value
assert_equal
true
,
m
.
bool
.
value
assert_equal
'str'
,
m
.
string_as_value
assert_equal
'str'
,
m
.
string
.
value
assert_equal
true
,
m
.
bool_as_value
assert_equal
"st
\n
r"
,
m
.
string_as_value
assert_equal
"st
\n
r"
,
m
.
string
.
value
assert_equal
"st
\n
r"
,
m
.
string_as_value
assert_equal
'fun'
,
m
.
bytes_as_value
assert_equal
'fun'
,
m
.
bytes
.
value
assert_equal
'fun'
,
m
.
bytes_as_value
}
m
=
proto_module
::
Wrapper
.
new
(
double:
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
),
float:
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
),
int32:
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
),
int64:
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
),
uint32:
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
),
uint64:
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
),
bool:
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
),
string:
Google
::
Protobuf
::
StringValue
.
new
(
value:
"st
\n
r"
),
bytes:
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
),
real_string:
'100'
)
run_asserts
.
call
(
m
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m
)
m2
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m2
)
# Test the case where we are serializing directly from the parsed form
# (before anything lazy is materialized).
m3
=
proto_module
::
Wrapper
::
decode
(
serialized
)
serialized2
=
proto_module
::
Wrapper
::
encode
(
m3
)
m4
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
run_asserts
.
call
(
m4
)
# Test that the lazy form compares equal to the expanded form.
m5
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
assert_equal
m5
,
m
serialized_json
=
proto_module
::
Wrapper
::
encode_json
(
m
)
m6
=
proto_module
::
Wrapper
::
decode_json
(
serialized_json
)
assert_equal
m6
,
m
end
def
test_repeated_wrappers
run_asserts
=
->
(
m
)
{
assert_equal
2.0
,
m
.
repeated_double
[
0
].
value
assert_equal
4.0
,
m
.
repeated_float
[
0
].
value
assert_equal
3
,
m
.
repeated_int32
[
0
].
value
assert_equal
4
,
m
.
repeated_int64
[
0
].
value
assert_equal
5
,
m
.
repeated_uint32
[
0
].
value
assert_equal
6
,
m
.
repeated_uint64
[
0
].
value
assert_equal
true
,
m
.
repeated_bool
[
0
].
value
assert_equal
'str'
,
m
.
repeated_string
[
0
].
value
assert_equal
'fun'
,
m
.
repeated_bytes
[
0
].
value
}
m
=
proto_module
::
Wrapper
.
new
(
repeated_double:
[
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
)],
repeated_float:
[
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
)],
repeated_int32:
[
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
)],
repeated_int64:
[
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
)],
repeated_uint32:
[
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
)],
repeated_uint64:
[
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
)],
repeated_bool:
[
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
)],
repeated_string:
[
Google
::
Protobuf
::
StringValue
.
new
(
value:
'str'
)],
repeated_bytes:
[
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
)],
)
run_asserts
.
call
(
m
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m
)
m2
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m2
)
# Test the case where we are serializing directly from the parsed form
# (before anything lazy is materialized).
m3
=
proto_module
::
Wrapper
::
decode
(
serialized
)
serialized2
=
proto_module
::
Wrapper
::
encode
(
m3
)
m4
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
run_asserts
.
call
(
m4
)
# Test that the lazy form compares equal to the expanded form.
m5
=
proto_module
::
Wrapper
::
decode
(
serialized2
)
assert_equal
m5
,
m
# Test JSON.
serialized_json
=
proto_module
::
Wrapper
::
encode_json
(
m5
)
m6
=
proto_module
::
Wrapper
::
decode_json
(
serialized_json
)
run_asserts
.
call
(
m6
)
assert_equal
m6
,
m
end
def
test_wrapper_setters_as_value
m
=
proto_module
::
Wrapper
.
new
def
test_oneof_wrappers
run_test
=
->
(
m
)
{
serialized
=
proto_module
::
Wrapper
::
encode
(
m
)
m2
=
proto_module
::
Wrapper
::
decode
(
serialized
)
# Encode directly from lazy form.
serialized2
=
proto_module
::
Wrapper
::
encode
(
m2
)
assert_equal
m
,
m2
assert_equal
serialized
,
serialized2
serialized_json
=
proto_module
::
Wrapper
::
encode_json
(
m
)
m3
=
proto_module
::
Wrapper
::
decode_json
(
serialized_json
)
assert_equal
m
,
m3
}
m
=
proto_module
::
Wrapper
.
new
()
run_test
.
call
(
m
)
m
.
oneof_double_as_value
=
2.0
run_test
.
call
(
m
)
m
.
oneof_float_as_value
=
4.0
run_test
.
call
(
m
)
m
.
oneof_int32_as_value
=
3
run_test
.
call
(
m
)
m
.
oneof_int64_as_value
=
5
run_test
.
call
(
m
)
m
.
oneof_uint32_as_value
=
6
run_test
.
call
(
m
)
m
.
oneof_uint64_as_value
=
7
run_test
.
call
(
m
)
m
.
oneof_string_as_value
=
'str'
run_test
.
call
(
m
)
m
.
oneof_bytes_as_value
=
'fun'
run_test
.
call
(
m
)
end
def
test_top_level_wrappers
# We don't expect anyone to do this, but we should also make sure it does
# the right thing.
run_test
=
->
(
klass
,
val
)
{
m
=
klass
.
new
(
value:
val
)
serialized
=
klass
::
encode
(
m
)
m2
=
klass
::
decode
(
serialized
)
# Encode directly from lazy form.
serialized2
=
klass
::
encode
(
m2
)
assert_equal
m
,
m2
assert_equal
serialized
,
serialized2
serialized_json
=
klass
::
encode_json
(
m
)
# This is nonsensical to do and does not work. There is no good reason
# to parse a wrapper type directly.
assert_raise
(
RuntimeError
)
{
klass
::
decode_json
(
serialized_json
)
}
}
run_test
.
call
(
Google
::
Protobuf
::
DoubleValue
,
2.0
)
run_test
.
call
(
Google
::
Protobuf
::
FloatValue
,
4.0
)
run_test
.
call
(
Google
::
Protobuf
::
Int32Value
,
3
)
run_test
.
call
(
Google
::
Protobuf
::
Int64Value
,
4
)
run_test
.
call
(
Google
::
Protobuf
::
UInt32Value
,
5
)
run_test
.
call
(
Google
::
Protobuf
::
UInt64Value
,
6
)
run_test
.
call
(
Google
::
Protobuf
::
BoolValue
,
true
)
run_test
.
call
(
Google
::
Protobuf
::
StringValue
,
'str'
)
run_test
.
call
(
Google
::
Protobuf
::
BytesValue
,
'fun'
)
end
def
test_wrapper_setters_as_value
run_asserts
=
->
(
m
)
{
m
.
double_as_value
=
4.8
assert_equal
4.8
,
m
.
double_as_value
assert_equal
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
4.8
),
m
.
double
...
...
@@ -1357,11 +1512,32 @@ module CommonTests
m
.
bytes_as_value
=
nil
assert_nil
m
.
bytes
assert_nil
m
.
bytes_as_value
end
}
def
test_wrapper_setters
m
=
proto_module
::
Wrapper
.
new
m2
=
proto_module
::
Wrapper
.
new
(
double:
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
),
float:
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
),
int32:
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
),
int64:
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
),
uint32:
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
),
uint64:
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
),
bool:
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
),
string:
Google
::
Protobuf
::
StringValue
.
new
(
value:
'str'
),
bytes:
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
),
real_string:
'100'
)
run_asserts
.
call
(
m2
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m2
)
m3
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m3
)
end
def
test_wrapper_setters
run_asserts
=
->
(
m
)
{
m
.
double
=
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
4.8
)
assert_equal
4.8
,
m
.
double_as_value
assert_equal
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
4.8
),
m
.
double
...
...
@@ -1417,15 +1593,38 @@ module CommonTests
m
.
bytes
=
nil
assert_nil
m
.
bytes
assert_nil
m
.
bytes_as_value
}
m
=
proto_module
::
Wrapper
.
new
run_asserts
.
call
(
m
)
m2
=
proto_module
::
Wrapper
.
new
(
double:
Google
::
Protobuf
::
DoubleValue
.
new
(
value:
2.0
),
float:
Google
::
Protobuf
::
FloatValue
.
new
(
value:
4.0
),
int32:
Google
::
Protobuf
::
Int32Value
.
new
(
value:
3
),
int64:
Google
::
Protobuf
::
Int64Value
.
new
(
value:
4
),
uint32:
Google
::
Protobuf
::
UInt32Value
.
new
(
value:
5
),
uint64:
Google
::
Protobuf
::
UInt64Value
.
new
(
value:
6
),
bool:
Google
::
Protobuf
::
BoolValue
.
new
(
value:
true
),
string:
Google
::
Protobuf
::
StringValue
.
new
(
value:
'str'
),
bytes:
Google
::
Protobuf
::
BytesValue
.
new
(
value:
'fun'
),
real_string:
'100'
)
run_asserts
.
call
(
m2
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m2
)
m3
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m3
)
end
def
test_wrappers_only
m
=
proto_module
::
Wrapper
.
new
(
real_string:
'hi'
,
oneof_string
:
'there'
)
m
=
proto_module
::
Wrapper
.
new
(
real_string:
'hi'
,
string_in_oneof
:
'there'
)
assert_raise
(
NoMethodError
)
{
m
.
real_string_as_value
}
assert_raise
(
NoMethodError
)
{
m
.
as_value
}
assert_raise
(
NoMethodError
)
{
m
.
_as_value
}
assert_raise
(
NoMethodError
)
{
m
.
oneof_string
_as_value
}
assert_raise
(
NoMethodError
)
{
m
.
string_in_oneof
_as_value
}
m
=
proto_module
::
Wrapper
.
new
m
.
string_as_value
=
'you'
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment