Skip to content
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

Merged
merged 10 commits into from Feb 2, 2015

Conversation

cfallin
Copy link
Contributor

@cfallin cfallin commented Jan 14, 2015

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.

@cfallin
Copy link
Contributor Author

cfallin commented Jan 14, 2015

@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.
@cfallin
Copy link
Contributor Author

cfallin commented Jan 14, 2015

Updated Ruby code generator as well.


/*
* call-seq:
* Descriptor.oneofs => list of OneofDescriptors
Copy link
Member

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| }

?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@cfallin
Copy link
Contributor Author

cfallin commented Jan 15, 2015

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);
Copy link
Member

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.

Copy link
Contributor Author

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 =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move inside if() below.

Copy link
Contributor Author

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
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@cfallin
Copy link
Contributor Author

cfallin commented Feb 2, 2015

Thanks! PTAL.

uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs));

// oneof_case == 0 indicates no field set.
if (oneof_case == 0) {
Copy link
Member

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.

Copy link
Contributor Author

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.

haberman added a commit that referenced this pull request Feb 2, 2015
Support oneofs in MRI Ruby C extension.
@haberman haberman merged commit 17e4419 into protocolbuffers:master Feb 2, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants