From 6765ff04ebc9384dac43486bf4e2d1ec4fef9c47 Mon Sep 17 00:00:00 2001 From: Jan Weitz Date: Fri, 23 Feb 2018 16:55:45 +0100 Subject: [PATCH] Add stringMethodOptionsExtension This helper function can be used on service methods to read options, which extend method options by a string. e.g. It is possible to read "Some string" for a custom `my_method_option.bar` message option extension. See: https://developers.google.com/protocol-buffers/docs/proto#customoptions on how to define a custom extension and referencing is by a fieldID. ``` service MyService { rpc MyMethod(RequestType) returns(ResponseType) { option (my_method_option.bar) = "Some string"; } } ``` If `my_method_option.bar` was defined for `fieldID: 50000` one can reference it using protoc-gen-template like: ``` {{- stringMethodOptionsExtension 50000 .method }} ``` --- helpers/helpers.go | 103 +++++++++++++++++++++++++++++++-------------- 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/helpers/helpers.go b/helpers/helpers.go index 119365b..612f86c 100644 --- a/helpers/helpers.go +++ b/helpers/helpers.go @@ -101,37 +101,38 @@ var ProtoHelpersFuncMap = template.FuncMap{ } return slice.Index(int(i)).Interface() }, - "snakeCase": xstrings.ToSnakeCase, - "getProtoFile": getProtoFile, - "getMessageType": getMessageType, - "getEnumValue": getEnumValue, - "isFieldMessage": isFieldMessage, - "isFieldMessageTimeStamp": isFieldMessageTimeStamp, - "isFieldRepeated": isFieldRepeated, - "haskellType": haskellType, - "goType": goType, - "goZeroValue": goZeroValue, - "goTypeWithPackage": goTypeWithPackage, - "jsType": jsType, - "jsSuffixReserved": jsSuffixReservedKeyword, - "namespacedFlowType": namespacedFlowType, - "httpVerb": httpVerb, - "httpPath": httpPath, - "httpPathsAdditionalBindings": httpPathsAdditionalBindings, - "httpBody": httpBody, - "shortType": shortType, - "urlHasVarsFromMessage": urlHasVarsFromMessage, - "lowerGoNormalize": lowerGoNormalize, - "goNormalize": goNormalize, - "leadingComment": leadingComment, - "trailingComment": trailingComment, - "leadingDetachedComments": leadingDetachedComments, - "stringFieldExtension": stringFieldExtension, - "boolFieldExtension": boolFieldExtension, - "isFieldMap": isFieldMap, - "fieldMapKeyType": fieldMapKeyType, - "fieldMapValueType": fieldMapValueType, - "replaceDict": replaceDict, + "snakeCase": xstrings.ToSnakeCase, + "getProtoFile": getProtoFile, + "getMessageType": getMessageType, + "getEnumValue": getEnumValue, + "isFieldMessage": isFieldMessage, + "isFieldMessageTimeStamp": isFieldMessageTimeStamp, + "isFieldRepeated": isFieldRepeated, + "haskellType": haskellType, + "goType": goType, + "goZeroValue": goZeroValue, + "goTypeWithPackage": goTypeWithPackage, + "jsType": jsType, + "jsSuffixReserved": jsSuffixReservedKeyword, + "namespacedFlowType": namespacedFlowType, + "httpVerb": httpVerb, + "httpPath": httpPath, + "httpPathsAdditionalBindings": httpPathsAdditionalBindings, + "httpBody": httpBody, + "shortType": shortType, + "urlHasVarsFromMessage": urlHasVarsFromMessage, + "lowerGoNormalize": lowerGoNormalize, + "goNormalize": goNormalize, + "leadingComment": leadingComment, + "trailingComment": trailingComment, + "leadingDetachedComments": leadingDetachedComments, + "stringFieldExtension": stringFieldExtension, + "stringMethodOptionsExtension": stringMethodOptionsExtension, + "boolFieldExtension": boolFieldExtension, + "isFieldMap": isFieldMap, + "fieldMapKeyType": fieldMapKeyType, + "fieldMapValueType": fieldMapValueType, + "replaceDict": replaceDict, } var pathMap map[interface{}]*descriptor.SourceCodeInfo_Location @@ -234,6 +235,46 @@ func leadingDetachedComments(i interface{}) []string { return loc.GetLeadingDetachedComments() } +// stringMethodOptionsExtension extracts method options of a string type. +// To define your own extensions see: +// https://developers.google.com/protocol-buffers/docs/proto#customoptions +// Typically the fieldID of private extensions should be in the range: +// 50000-99999 +func stringMethodOptionsExtension(fieldID int32, f *descriptor.MethodDescriptorProto) string { + if f == nil { + return "" + } + if f.Options == nil { + return "" + } + var extendedType *descriptor.MethodOptions + var extensionType *string + + eds := proto.RegisteredExtensions(f.Options) + if eds[fieldID] == nil { + ed := &proto.ExtensionDesc{ + ExtendedType: extendedType, + ExtensionType: extensionType, + Field: fieldID, + Tag: fmt.Sprintf("bytes,%d", fieldID), + } + proto.RegisterExtension(ed) + eds = proto.RegisteredExtensions(f.Options) + } + + ext, err := proto.GetExtension(f.Options, eds[fieldID]) + if err != nil { + return "" + } + + str, ok := ext.(*string) + if !ok { + return "" + } + + return *str +} + func stringFieldExtension(fieldID int32, f *descriptor.FieldDescriptorProto) string { if f == nil { return ""