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
969d245b
Commit
969d245b
authored
Oct 21, 2019
by
Joshua Haberman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP: first steps towards lazily creating wrappers.
parent
9fdb2cf2
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
205 additions
and
41 deletions
+205
-41
encode_decode.c
ruby/ext/google/protobuf_c/encode_decode.c
+136
-2
message.c
ruby/ext/google/protobuf_c/message.c
+26
-20
common_tests.rb
ruby/tests/common_tests.rb
+43
-19
No files found.
ruby/ext/google/protobuf_c/encode_decode.c
View file @
969d245b
...
...
@@ -298,6 +298,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
;
...
...
@@ -541,6 +550,85 @@ static void add_handlers_for_repeated_field(upb_handlers *h,
}
}
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
size_t
stringwrapper_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
ptr
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
get_frozen_string
(
ptr
,
len
,
false
);
return
len
;
}
static
size_t
byteswrapper_handler
(
void
*
closure
,
const
void
*
hd
,
const
char
*
ptr
,
size_t
len
,
const
upb_bufhandle
*
handle
)
{
VALUE
*
rbval
=
closure
;
*
rbval
=
get_frozen_string
(
ptr
,
len
,
true
);
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
;
}
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 singular field.
static
void
add_handlers_for_singular_field
(
const
Descriptor
*
desc
,
upb_handlers
*
h
,
...
...
@@ -580,8 +668,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
));
upb_handlers_setstartsubmsg
(
h
,
f
,
submsg_handler
,
&
attr
);
break
;
if
(
is_wrapper
(
upb_fielddef_msgsubdef
(
f
)))
{
upb_handlers_setstartsubmsg
(
h
,
f
,
startwrapper
,
&
attr
);
}
else
{
upb_handlers_setstartsubmsg
(
h
,
f
,
submsg_handler
,
&
attr
);
}
}
}
}
...
...
@@ -623,6 +714,43 @@ 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_setstring
(
h
,
f
,
stringwrapper_handler
,
NULL
);
break
;
case
UPB_WELLKNOWN_BYTESVALUE
:
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
,
...
...
@@ -706,6 +834,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
);
...
...
ruby/ext/google/protobuf_c/message.c
View file @
969d245b
...
...
@@ -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,25 +108,28 @@ 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
;
static
bool
is_wrapper_type_field
(
const
upb_fielddef
*
field
)
{
const
upb_msgdef
*
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
)
{
if
(
is_wrapper_type_field
(
field
)
&&
value
!=
Qnil
)
{
VALUE
hash
=
rb_hash_new
();
rb_hash_aset
(
hash
,
rb_str_new2
(
"value"
),
value
);
{
...
...
@@ -194,7 +196,7 @@ static int extract_method_call(VALUE method_name, MessageHeader* self,
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,10 +331,14 @@ 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
;
}
return
value
;
}
else
if
(
accessor_type
==
METHOD_WRAPPER_SETTER
)
{
VALUE
wrapper
=
ruby_wrapper_type
(
self
->
descriptor
->
layout
,
f
,
argv
[
1
]);
layout_set
(
self
->
descriptor
->
layout
,
Message_data
(
self
),
f
,
wrapper
);
...
...
ruby/tests/common_tests.rb
View file @
969d245b
...
...
@@ -1266,6 +1266,44 @@ module CommonTests
end
def
test_wrapper_getters
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
true
,
m
.
bool_as_value
assert_equal
'str'
,
m
.
string_as_value
assert_equal
'str'
,
m
.
string
.
value
assert_equal
'str'
,
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
),
...
...
@@ -1279,24 +1317,10 @@ module CommonTests
real_string:
'100'
)
assert_equal
2.0
,
m
.
double_as_value
assert_equal
2.0
,
m
.
double
.
value
assert_equal
4.0
,
m
.
float_as_value
assert_equal
4.0
,
m
.
float
.
value
assert_equal
3
,
m
.
int32_as_value
assert_equal
3
,
m
.
int32
.
value
assert_equal
4
,
m
.
int64_as_value
assert_equal
4
,
m
.
int64
.
value
assert_equal
5
,
m
.
uint32_as_value
assert_equal
5
,
m
.
uint32
.
value
assert_equal
6
,
m
.
uint64_as_value
assert_equal
6
,
m
.
uint64
.
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
'fun'
,
m
.
bytes_as_value
assert_equal
'fun'
,
m
.
bytes
.
value
run_asserts
.
call
(
m
)
serialized
=
proto_module
::
Wrapper
::
encode
(
m
)
m2
=
proto_module
::
Wrapper
::
decode
(
serialized
)
run_asserts
.
call
(
m2
)
end
def
test_wrapper_setters_as_value
...
...
@@ -1443,7 +1467,7 @@ module CommonTests
assert_raise
(
NoMethodError
)
{
m
.
string_XXXXXXXXX
}
assert_raise
(
NoMethodError
)
{
m
.
string_XXXXXXXXXX
}
end
def
test_converts_time
m
=
proto_module
::
TimeMessage
.
new
...
...
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