-
Notifications
You must be signed in to change notification settings - Fork 15.6k
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
Add support for descriptor options in ruby interface #12828
Add support for descriptor options in ruby interface #12828
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
ruby/ext/google/protobuf_c/defs.c
Outdated
upb_Arena* arena = upb_Arena_New(); | ||
size_t size; | ||
char* serialized = google_protobuf_MessageOptions_serialize(opts, arena, &size); | ||
if (serialized) { |
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.
Please factor this part of the function into a static helper so that all of the functions you added can share it.
ruby/ext/google/protobuf_c/defs.c
Outdated
static void FileDescriptor_register(VALUE module) { | ||
VALUE klass = rb_define_class_under(module, "FileDescriptor", rb_cObject); | ||
rb_define_alloc_func(klass, FileDescriptor_alloc); | ||
rb_define_method(klass, "initialize", FileDescriptor_initialize, 3); | ||
rb_define_method(klass, "name", FileDescriptor_name, 0); | ||
rb_define_method(klass, "syntax", FileDescriptor_syntax, 0); | ||
rb_define_method(klass, "serialized_options", FileDescriptor_serialized_options, 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.
In the interest of keeping the public API small, can we make serialized_options
a private method?
@@ -451,6 +451,10 @@ def value(name, number) | |||
end | |||
end | |||
|
|||
def self.decode_options(klass, serialized_options) | |||
options = klass.decode(serialized_options) | |||
options.freeze |
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.
We want this freeze to be recursive. Otherwise a user could write something like:
# This works, because only my_descriptor.options itself is frozen.
my_descriptor.options.some_message_options.field = 5
We'll want to write a loop that visits all fields and freezes them all. I'm not sure how easy this will be to do in Ruby. We may want to do it in C.
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.
Thank you for the review. I've addressed the first 2 concerns (I think).
I have a question about the recursive freeze. The Message class already has a freeze
method that I am calling here. Should that method be updated to be recursive or should I create a separate deep_freeze
method for this use case?
Additionally, for the recursive freeze, should all fields also be pinned to the same arena?
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.
Message#freeze
follows the general Ruby semantics of only doing a shallow freeze. I don't think we should change that.
I think we could add deep_freeze
as an internal-only API, but I don't think we should make it public. We should keep new public APIs to a minimum, since each one will need to be reviewed and scrutinized.
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 added a deep_freeze
method as a private method on the message class. I understand this sorta exposes it as a public API (and I'm even cheating and calling it by using ruby's send
method).
I couldn't figure out a better way to hide it as an internal-only API. Open to suggestions. The only other thought I had would be to move the .options
methods into defs.c
, but that would require exposing some more of message.c
to allow decod
ing and deep_freeze
ing it.
ruby/ext/google/protobuf_c/message.c
Outdated
VALUE field = Message_getfield(_self, f); | ||
|
||
if (upb_FieldDef_IsMap(f) || upb_FieldDef_IsRepeated(f)) { | ||
rb_funcall(field, rb_intern("freeze"), 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.
Repeated fields and maps can contain messages, so we will need them to support deep_freeze
also.
ruby/ext/google/protobuf_c/message.c
Outdated
* | ||
* Deeep freezes the message object recursively. | ||
*/ | ||
static VALUE Message_deep_freeze(VALUE _self) { |
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.
Let's call it internal_deep_freeze
just so it's unambiguous that it's intended to be internal-only.
It doesn't make it harder to call, but if someone does call it they will know that it's an API that could change.
👋🏻 Hey @jsteinberg, is there anything I can help do to get this going again? |
Yes, I've unfortunately been busy at work so haven't gotten back to this. It's definitely on my backlog (along with adding extension support to ruby after this). So, I'm not sure what is needed to move forward here. I got a little bit of time this afternoon so happy to make any requested changes / rebase this off of main. |
It looks like I need to figure out how to make this work for JRuby. Its been a while since I've done anything with that. |
Oh interesting, there isn't an existing freeze method implemented in the Java version. Will be a bit more involved than just mirroring it like I first thought. |
If you have questions about JRuby I'm happy to help. |
@JasonLunn is it true that JRuby Protobuf doesn't support |
Sorry, I didn't end up getting around to this and then had some vacation around the holiday. I have essentially zero JRuby knowledge (I used it once...) and since the CI tests were not enabled for this branch, I didn't realize I had omitted the necessary changes. I can try to get JRuby running locally so I can run the tests and try to figure out what is missing, but if someone else with much more knowledge wants to do it then I'm not going to stop you. I have limited time this week but I will try to at least start making progress on this. |
It looks like I need to implement NameError: undefined local variable or method `serialized_options' for #<Google::Protobuf::FileDescriptor:0x644947ee> Additionally, I need to implement the NoMethodError: undefined method `internal_deep_freeze' for #<BasicTest::TestDeprecatedMessage:0x65259c53> |
JRuby as a language supports @jsteinberg - feel free to ping me if you have any JRuby-specific questions. |
Rewrrte and extension of #12828, with additional work for JRuby. Partially fixes #1198 by adding support for custom options. Handling of extensions will be handled in a follow up. Also includes these unrelated fixes: * Removes code echo between `google/protobuf/repeated_field.rb` and `google/protobuf/ffi/repeated_field.rb` by `require`'ing the former in the latter. * Adds missing calles to `testFrozen()` from methods of `RepeatedField` under JRuby that mutate. * Various typos in comments. Closes #14594 COPYBARA_INTEGRATE_REVIEW=#14594 from protocolbuffers:add-support-for-options-in-ruby 16cc9e3 PiperOrigin-RevId: 580848874
We triage inactive PRs and issues in order to make it easier to find active work. If this PR should remain active, please add a comment. This PR is labeled |
Rewrrte and extension of #12828, with additional work for JRuby. Partially fixes #1198 by adding support for custom options. Handling of extensions will be handled in a follow up. Also includes these unrelated fixes: * Removes code echo between `google/protobuf/repeated_field.rb` and `google/protobuf/ffi/repeated_field.rb` by `require`'ing the former in the latter. * Adds missing calles to `testFrozen()` from methods of `RepeatedField` under JRuby that mutate. * Various typos in comments. Closes #14594 COPYBARA_INTEGRATE_REVIEW=#14594 from protocolbuffers:add-support-for-options-in-ruby 16cc9e3 PiperOrigin-RevId: 580848874
Rewrrte and extension of #12828, with additional work for JRuby. Partially fixes #1198 by adding support for custom options. Handling of extensions will be handled in a follow up. Also includes these unrelated fixes: * Removes code echo between `google/protobuf/repeated_field.rb` and `google/protobuf/ffi/repeated_field.rb` by `require`'ing the former in the latter. * Adds missing calles to `testFrozen()` from methods of `RepeatedField` under JRuby that mutate. * Various typos in comments. Closes #14594 COPYBARA_INTEGRATE_REVIEW=#14594 from protocolbuffers:add-support-for-options-in-ruby 16cc9e3 PiperOrigin-RevId: 580848874
We triage inactive PRs and issues in order to make it easier to find active work. If this PR should remain active or becomes active again, please reopen it. This PR was closed and archived because there has been no new activity in the 14 days since the |
Add support for descriptor options in Ruby:
spawned off of discussion here
Notes:
EnumValueOptions
/ServiceOptions
/MethodOptions
were not included. There are not ruby interfaces forEnumValueDescriptorProto
/ServiceDescriptorProto
/MethodDescriptorProto
. If we want to add those first I could look into that.# We actually need to freeze recursively.
. I did not implement that yet and am looking for guidance.Message_freeze
method?SubMessage
/Repeated
/Map
?)