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

Accessing custom MessageOptions #392

Closed
dwaynebradley opened this issue Feb 20, 2019 · 7 comments
Closed

Accessing custom MessageOptions #392

dwaynebradley opened this issue Feb 20, 2019 · 7 comments

Comments

@dwaynebradley
Copy link

I have been attempting to figure out how to access custom MessageOptions in rust-protobuf. If we look at the protobuf documentation for Custom Options you see this example:

import "google/protobuf/descriptor.proto";

extend google.protobuf.MessageOptions {
  optional string my_option = 51234;
}

message MyMessage {
  option (my_option) = "Hello world!";
}

The documentation also show how to access this custom option using C++:

string value = MyMessage::descriptor()->options().GetExtension(my_option);

I have attempted to follow the same pattern using this library starting with something like the following:

let msg_desc = MyMessage::descriptor_static();

This gives me a &'static protobuf::reflect::MessageDescriptor and from here I'm lost. There is a private proto field in MessageDescriptor which is of type &'static DescriptorProto. The DescriptorProto struct has the options field that appears to be what I'm after but I cannot access it since proto is private.

Where am I going wrong?

@stepancheg
Copy link
Owner

Should be your_mod::exts::my_option.get(message_description_options)

However, the problem is that MessageDescriptor object does not expose DescriptorProto object. I should fix that.

At the moment you can obtain DescriptorProto from FileDescriptorProto which can be obtained by calling your_mod::file_descriptor_proto().

@stepancheg
Copy link
Owner

Also, at the moment only bool options are implemented. Again, I'll fix it now.

@stepancheg
Copy link
Owner

OK, master now support extensions: 0837187

protoc-based codegen supports all extensions, and pure rust codegen supports only a subset of types (in particular, pure rust doesn't support extensions of type message or enum). String extensions as in your example are supported.

Now I need to backport it to stable.

@dwaynebradley
Copy link
Author

Thanks @stepancheg for the really quick turnaround! I'll look at is later today and check it out.

@dwaynebradley
Copy link
Author

Just to follow up...

I was able to create my custom boolean option and apply it to a message successfully! Thanks for the quick fix on this @stepancheg! Here is some generic code that I modelled my code after to check for the option.

Protobuf definition

import "google/protobuf/descriptor.proto";

extend google.protobuf.MessageOptions {
  bool my_custom_bool_option = 51234;
}

message MyMessage {
  option (my_custom_bool_option) = true;
}

Rust code example

    let my_bool_option = my_module::exts::my_custom_bool_option;

    let my_descriptor = my_module::MyMessage::descriptor_static();
    let my_message_options = my_descriptor.get_proto().options.as_ref();
    match my_message_options {
        Some(have_message_options) => {
            // There are some options defined for this message
            // Now check to see if my_custom_bool_option has been
            // has been defined for this message
            let o = my_bool_option.get(&have_message_options);
            match o {
                Some(is_set) => {
                    // my_custom_bool_option is defined for this message
                    // but is it set to "true" or "false"?
                    if is_set {
                        println!("my_custom_bool_option is true!!!");
                    } else {
                        println!("my_custom_bool_option is false!!!");
                    }
                }
                None => {
                    println!("my_custom_bool_option NOT defined for this message!!!");
                }
            }
        }
        None => {
            // There are no options defined for this message
            println!("No options defined!!!");
        }
    }

There may be a better "rust-ish" way of doing this but this appears to work for me. Hopefully this can help someone else down the line.

@stepancheg
Copy link
Owner

There may be a better "rust-ish" way of doing this

API change suggestions are highly appreciated. But please note that that API changes won't be backported to the stable branch, and will be released on new major version.

option (my_custom_bool_option) = true;

As I said, string options should work too (in master).

And a general comment. Extensions are not a very popular feature of protobuf, they are not even part of protobuf syntax version 3. That's why I was not in a hurry implementing them.

@stepancheg
Copy link
Owner

Published a version 2.4.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants