-
Notifications
You must be signed in to change notification settings - Fork 1.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
Implement custom options #179
Comments
I just bumped into the exact same issue. Is there a workaround? |
|
I am also not able to get custom options working correctly with proto3 in golang. I used the same .proto file supplied in the original post and the same main() functionality. I get this error:
Here is the auto-generated go file: type MyMessage struct {
}
func (m *MyMessage) Reset() { *m = MyMessage{} }
func (m *MyMessage) String() string { return proto.CompactTextString(m) }
func (*MyMessage) ProtoMessage() {}
func (*MyMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
var E_Foo = &proto.ExtensionDesc{
ExtendedType: (*google_protobuf.MessageOptions)(nil),
ExtensionType: (*string)(nil),
Field: 50001,
Name: "foo",
Tag: "bytes,50001,opt,name=foo",
}
func init() {
proto.RegisterType((*MyMessage)(nil), "MyMessage")
proto.RegisterExtension(E_Foo)
}
func init() { proto.RegisterFile("example.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 129 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0xad, 0x48, 0xcc,
0x2d, 0xc8, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x97, 0x52, 0x48, 0xcf, 0xcf, 0x4f, 0xcf,
0x49, 0xd5, 0x07, 0xf3, 0x92, 0x4a, 0xd3, 0xf4, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a,
0xf2, 0x8b, 0x20, 0x2a, 0x94, 0x44, 0xb8, 0x38, 0x7d, 0x2b, 0x7d, 0x53, 0x8b, 0x8b, 0x13, 0xd3,
0x53, 0xad, 0xd8, 0xbb, 0xb6, 0x4a, 0x30, 0x27, 0x25, 0x16, 0x59, 0x19, 0x73, 0x31, 0xa7, 0xe5,
0xe7, 0x0b, 0xc9, 0xeb, 0x41, 0xf4, 0xeb, 0xc1, 0xf4, 0xeb, 0x41, 0x55, 0xfa, 0x17, 0x94, 0x64,
0xe6, 0xe7, 0x15, 0x4b, 0x5c, 0x6c, 0x63, 0x56, 0x60, 0xd4, 0xe0, 0x0c, 0x02, 0xa9, 0x4e, 0x62,
0x03, 0xab, 0x32, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x4c, 0xa2, 0x4c, 0x3c, 0x84, 0x00, 0x00,
0x00,
} Let me know if I am doing anything wrong or if you need more information. |
I have the same issue. How can I get the descriptor of a proto? |
Does anyone know whether this is supported or not? I tried to look the source tree, but I couldn't find any clue. |
m := test.MyMessage{}
ex, err = proto.GetExtension(&m, test.E_Foo) is definitely not the way to get options for the message. They're set as extensions on the I don't think the Once you have the |
Thanks for the information. I could access
Is this the right way to do that? |
Yep, that sounds about right. I'm not sure it's a huge amount of work to just provide a library that does all that; I'll see what I can do this week. |
You should be able to use the new @kerinin's example should be something like: import (
…
"github.com/golang/protobuf/descriptor"
)
func main() {
m := test.MyMessage{}
_, md := descriptor.ForMessage(&m)
ex, err = proto.GetExtension(md, test.E_Foo)
fmt.Printf("MyMessage.GetExtension: %+v, %+v\n", *ex.(*string), err)
} |
It's not working for me... fd and md returned by the ForMessage () func is always google/protobuf/descriptor.proto and DescriptorProto respectively because my proto files import that. In my proto file Booking.proto: package com.example and calling ForMessage(descriptor) where descriptor is the *DescriptorProto of my message "BookingStatus", just gives me google/protobuf/descriptor.proto and DescriptorProto |
For those following this thread the example above no longer works and should be: import (
…
"github.com/golang/protobuf/descriptor"
)
func main() {
m := test.MyMessage{}
_, md := descriptor.ForMessage(&m)
ex, err = proto.GetExtension(md.Options, test.E_Foo) // "md.Options" not "md"
fmt.Printf("MyMessage.GetExtension: %+v, %+v\n", *ex.(*string), err)
} |
Thanks @ericchiang |
@bcmills ' func main() {
} |
To look at enum options, you'll want to look in the In the |
Dear @neild , below is the sample enum definition for me for which the e_format_str is registered as well
I get the generated enum go code. This type does not satisfy the interface to use descriptor.ForMessage() as the generate ENUM does not use Descriptor() method but EnumDescriptor() method. so I'm fetching the FileDescriptor with EnumDescriptor() and doing GUNZIP myself and able to reach upto EnumDescriptorProto and can get EnumValueDescriptor as well from it. But I'm getting the whole lot of information for the whole file with which to traverse by specifying indices and this approach will not help me as if there are more enums defined in same file or more enum values are added it can distort the indices. Below is my debug raw code :
The above snippet is giving me a good details but not exactly for the value which I want to as I'm going via FileDescriptorProto. I'm sure I've not been able to comprehend the godoc guide properly for protobuf structure and there would be a way to directly pin point to the 'options' for the enum value which I instantiated. Is there any way with which I can get Options for the particular enum value just by passing the 'XYZ_IN_PROGRESS' or '123' |
Currently, you will need to traverse the FileDescriptorProto until you find the enum descriptor you're looking for. For example, var fd *descpb.FileDescriptorProto // get this from somewhere, as above
for _, ed := range fd.EnumType {
if ed.Name() == "proto.package.name.abc" {
// use this descriptor
}
} Note that if the enum is nested in a message, you will need to traverse into the DescriptorProto for that message to find it. The definition of the descriptor protos is here: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/descriptor.proto) Once you have an EnumDescriptorProto, you can fetch your option from it: xo, err = proto.GetExtension(ed.Options, testpb.E_EFormatStr) As I mentioned above, this is all quite a bit simpler in the upcoming ext := proto.GetExtension(somepb.Enum_VALUE.Descriptor().Options(), testpb.E_EFormatStr) |
@neild : I understood it now, will give it a try. Thanks a lot for your help. Hope this conversation helps other people as well. |
@ALL , I'll add one more hierarchy in conjunction to @neild 's response to my question so that Options for the enum are read without fail. func GetEnumOption(ErrorEnum *pb.errEnum) string {
gz, _ := ErrorEnum.EnumDescriptor()
fd, err := extractFile(gz) // get FD from generated code and extract it
if err != nil {
// Error
}
enumStr := ErrorEnum.String()
for _, ed := range fd.GetEnumType() {
for _, enumValueDescriptor := range ed.GetValue() {
if enumValueDescriptor.GetName() == enumStr {
if enumValueDescriptor.Options != nil { // In case any Enum has not implemented any option
enumStrDescr, err := proto.GetExtension(enumValueDescriptor.Options, pb.E_EFormatStr)
if err != nil {
glog.Errorf("Error while fetching option for enum: %s", enumStr)
//error
}
return *enumStrDescr.(*string)
} else {
glog.Infof("Enum: %s does not have options ", enumStr)
}
}
}
}
// return
} Thanks. |
This provides a more reasonable API for obtaining a FileDescriptorProto and DescriptorProto for a given proto.Message — a process that is currently possible (but undocumented) using the public proto API. The major use case for obtaining a DescriptorProto is to decode custom message options, which are encoded as extensions on the MessageOptions submessage. (See https://developers.google.com/protocol-buffers/docs/proto#customoptions.) Fixes golang/protobuf#179. PiperOriGin-RevId: 139356528
Custom option types appear to be broken - generated types do not implement
ExtensionMap
. Example protobuf definition:Attempting to access the option fails:
GetExtension
succeeds with the original descriptor types (MessageOptions
etc) if the extension defines a default type, but that provides pretty limited utility.The text was updated successfully, but these errors were encountered: