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
e2debef5
Commit
e2debef5
authored
Jan 15, 2015
by
Chris Fallin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Ruby extension: added oneof accessor.
parent
e1b7d38d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
53 additions
and
1 deletion
+53
-1
encode_decode.c
ruby/ext/google/protobuf_c/encode_decode.c
+2
-1
message.c
ruby/ext/google/protobuf_c/message.c
+45
-0
basic.rb
ruby/tests/basic.rb
+6
-0
No files found.
ruby/ext/google/protobuf_c/encode_decode.c
View file @
e2debef5
...
...
@@ -77,7 +77,8 @@ static const void *newoneofhandlerdata(upb_handlers *h,
// we don't expose these numbers to the user, so the only requirement is that
// we have some unique ID for each union case/possibility. The field tag
// numbers are already present and are easy to use so there's no reason to
// create a separate ID space.
// create a separate ID space. In addition, using the field tag number here
// lets us easily look up the field in the oneof accessor.
hd
->
oneof_case_num
=
upb_fielddef_number
(
f
);
if
(
upb_fielddef_type
(
f
)
==
UPB_TYPE_MESSAGE
)
{
hd
->
md
=
upb_fielddef_msgsubdef
(
f
);
...
...
ruby/ext/google/protobuf_c/message.c
View file @
e2debef5
...
...
@@ -70,6 +70,36 @@ VALUE Message_alloc(VALUE klass) {
return
ret
;
}
static
VALUE
which_oneof_field
(
MessageHeader
*
self
,
const
upb_oneofdef
*
o
)
{
// If no fields in the oneof, always nil.
if
(
upb_oneofdef_numfields
(
o
)
==
0
)
{
return
Qnil
;
}
// Grab the first field in the oneof so we can get its layout info to find the
// oneof_case field.
upb_oneof_iter
it
;
upb_oneof_begin
(
&
it
,
o
);
assert
(
!
upb_oneof_done
(
&
it
));
const
upb_fielddef
*
first_field
=
upb_oneof_iter_field
(
&
it
);
assert
(
upb_fielddef_containingoneof
(
first_field
)
!=
NULL
);
size_t
case_ofs
=
self
->
descriptor
->
layout
->
fields
[
upb_fielddef_index
(
first_field
)].
case_offset
;
uint32_t
oneof_case
=
*
((
uint32_t
*
)(
Message_data
(
self
)
+
case_ofs
));
// oneof_case == 0 indicates no field set.
if
(
oneof_case
==
0
)
{
return
Qnil
;
}
// oneof_case is a field index, so find that field.
const
upb_fielddef
*
f
=
upb_oneofdef_itof
(
o
,
oneof_case
);
assert
(
f
!=
NULL
);
return
ID2SYM
(
rb_intern
(
upb_fielddef_name
(
f
)));
}
/*
* call-seq:
* Message.method_missing(*args)
...
...
@@ -82,6 +112,10 @@ VALUE Message_alloc(VALUE klass) {
*
* msg.foo = 42
* puts msg.foo
*
* This method also provides read-only accessors for oneofs. If a oneof exists
* with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
* the name of the field in that oneof that is currently set, or nil if none.
*/
VALUE
Message_method_missing
(
int
argc
,
VALUE
*
argv
,
VALUE
_self
)
{
MessageHeader
*
self
;
...
...
@@ -104,6 +138,17 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
name_len
--
;
}
// Check for a oneof name first.
const
upb_oneofdef
*
o
=
upb_msgdef_ntoo
(
self
->
descriptor
->
msgdef
,
name
,
name_len
);
if
(
o
!=
NULL
)
{
if
(
setter
)
{
rb_raise
(
rb_eRuntimeError
,
"Oneof accessors are read-only."
);
}
return
which_oneof_field
(
self
,
o
);
}
// Otherwise, check for a field with that name.
const
upb_fielddef
*
f
=
upb_msgdef_ntof
(
self
->
descriptor
->
msgdef
,
name
,
name_len
);
...
...
ruby/tests/basic.rb
View file @
e2debef5
...
...
@@ -615,30 +615,35 @@ module BasicTest
assert
d
.
b
==
nil
assert
d
.
c
==
nil
assert
d
.
d
==
nil
assert
d
.
my_oneof
==
nil
d
.
a
=
"hi"
assert
d
.
a
==
"hi"
assert
d
.
b
==
nil
assert
d
.
c
==
nil
assert
d
.
d
==
nil
assert
d
.
my_oneof
==
:a
d
.
b
=
42
assert
d
.
a
==
nil
assert
d
.
b
==
42
assert
d
.
c
==
nil
assert
d
.
d
==
nil
assert
d
.
my_oneof
==
:b
d
.
c
=
TestMessage2
.
new
(
:foo
=>
100
)
assert
d
.
a
==
nil
assert
d
.
b
==
nil
assert
d
.
c
.
foo
==
100
assert
d
.
d
==
nil
assert
d
.
my_oneof
==
:c
d
.
d
=
:C
assert
d
.
a
==
nil
assert
d
.
b
==
nil
assert
d
.
c
==
nil
assert
d
.
d
==
:C
assert
d
.
my_oneof
==
:d
d2
=
OneofMessage
.
decode
(
OneofMessage
.
encode
(
d
))
assert
d2
==
d
...
...
@@ -669,6 +674,7 @@ module BasicTest
d5
.
a
=
nil
assert
d5
.
a
==
nil
assert
OneofMessage
.
encode
(
d5
)
==
''
assert
d5
.
my_oneof
==
nil
end
def
test_enum_field
...
...
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