New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support oneofs in MRI Ruby C extension. #168
Conversation
@haberman to review. |
- A golden-file test that ensures protoc produces known-valid output. - A Ruby test that loads that golden file and ensures it actually works with the extension. This split strategy allows us to test end-to-end without needing to integrate the Ruby gem build system and the protoc build system. This is desirable because we do not want a gem build/install to depend on building protoc, and we do not want building protoc to depend on building and testing the gem.
Updated Ruby code generator as well. |
|
||
/* | ||
* call-seq: | ||
* Descriptor.oneofs => list of OneofDescriptors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More idiomatic to define:
Descriptor.each_oneof { |oneof| }
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Thanks! PTAL. |
@@ -65,6 +65,10 @@ static upb_fielddef* check_field_notfrozen(const upb_fielddef* def) { | |||
return (upb_fielddef*)check_notfrozen((const upb_def*)def); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
upb_downcast_fielddef() / UPB_UPCAST(). Should be safer than doing casts directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
desc->layout->offsets[upb_fielddef_index(f)] + sizeof(MessageHeader); | ||
desc->layout->fields[upb_fielddef_index(f)].offset + | ||
sizeof(MessageHeader); | ||
uint32_t oneof_case_offset = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move inside if() below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
rb_class_new_instance(0, NULL, subklass); | ||
} | ||
// Set the oneof case *after* allocating the new class instance -- see comment | ||
// in layout_set() as to why. There are subtle interactions with possible GC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would specifically mention here that the key invariant is that setting of data and case are atomic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Thanks! PTAL. |
uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs)); | ||
|
||
// oneof_case == 0 indicates no field set. | ||
if (oneof_case == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use ONEOF_CASE_NONE and rm comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed that one, sorry! Grepped for oneof_case
and I don't think there are any more literal zeroes. Done.
Support oneofs in MRI Ruby C extension.
This PR adds support for oneofs -- in the defs, in message objects, and during parsing and serialization -- to the Ruby extension. The API impact is minimal: fields that are part of a oneof can now take on a
nil
value to indicate not-present, and at most one field in a oneof may be present (non-nil).This includes a (necessary) update of the upb amalgamation up to git commit
1988a660
.