Skip to content

Commit

Permalink
Merge pull request #108 from t-yuki/feature/enum
Browse files Browse the repository at this point in the history
Add parser and swagger support for enum, no gengateway yet
  • Loading branch information
yugui committed Feb 16, 2016
2 parents f96da81 + 3ca4494 commit 4ce23d2
Show file tree
Hide file tree
Showing 9 changed files with 307 additions and 121 deletions.
194 changes: 125 additions & 69 deletions examples/examplepb/a_bit_of_everything.pb.go

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion examples/examplepb/a_bit_of_everything.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ message ABitOfEverything {
message Nested {
string name = 1;
uint32 amount = 2;
enum DeepEnum {
FALSE = 0;
TRUE = 1;
}
DeepEnum ok = 3;
}

string uuid = 1;
Expand All @@ -24,11 +29,12 @@ message ABitOfEverything {
string string_value = 11;
// TODO(yugui) add bytes_value
uint32 uint32_value = 13;
// TODO(yugui) add enum_value
NumericEnum enum_value = 14;
sfixed32 sfixed32_value = 15;
sfixed64 sfixed64_value = 16;
sint32 sint32_value = 17;
sint64 sint64_value = 18;
repeated string repeated_string_value = 19;
}

message EmptyMessage {
Expand All @@ -38,8 +44,14 @@ message IdMessage {
string uuid = 1;
}

enum NumericEnum {
ZERO = 0;
ONE = 1;
}

service ABitOfEverythingService {
rpc Create(ABitOfEverything) returns (ABitOfEverything) {
// TODO add enum_value
option (google.api.http) = {
post: "/v1/example/a_bit_of_everything/{float_value}/{double_value}/{int64_value}/separator/{uint64_value}/{int32_value}/{fixed64_value}/{fixed32_value}/{bool_value}/{string_value=strprefix/*}/{uint32_value}/{sfixed32_value}/{sfixed64_value}/{sint32_value}/{sint64_value}"
};
Expand Down
15 changes: 13 additions & 2 deletions examples/examplepb/streamless_everything.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ message ABitOfEverything {
message Nested {
string name = 1;
uint32 amount = 2;
enum DeepEnum {
FALSE = 0;
TRUE = 1;
}
DeepEnum ok = 3;
}

string uuid = 1;
Expand All @@ -24,12 +29,12 @@ message ABitOfEverything {
string string_value = 11;
// TODO(yugui) add bytes_value
uint32 uint32_value = 13;
// TODO(yugui) add enum_value
NumericEnum enum_value = 14;
sfixed32 sfixed32_value = 15;
sfixed64 sfixed64_value = 16;
sint32 sint32_value = 17;
sint64 sint64_value = 18;
repeated string repeated_string_value = 19;
repeated string repeated_string_value = 19;
}

message EmptyMessage {
Expand All @@ -39,8 +44,14 @@ message IdMessage {
string uuid = 1;
}

enum NumericEnum {
ZERO = 0;
ONE = 1;
}

service ABitOfEverythingService {
rpc Create(ABitOfEverything) returns (ABitOfEverything) {
// TODO add enum_value
option (google.api.http) = {
post: "/v1/example/a_bit_of_everything/{float_value}/{double_value}/{int64_value}/separator/{uint64_value}/{int32_value}/{fixed64_value}/{fixed32_value}/{bool_value}/{string_value=strprefix/*}/{uint32_value}/{sfixed32_value}/{sfixed64_value}/{sint32_value}/{sint64_value}"
};
Expand Down
22 changes: 22 additions & 0 deletions examples/examplepb/streamless_everything.swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,20 @@
"name": {
"type": "string",
"format": "string"
},
"ok": {
"$ref": "#/definitions/NestedDeepEnum"
}
}
},
"NestedDeepEnum": {
"type": "string",
"enum": [
"FALSE",
"TRUE"
],
"default": "FALSE"
},
"examplepbABitOfEverything": {
"properties": {
"bool_value": {
Expand All @@ -279,6 +290,9 @@
"type": "number",
"format": "double"
},
"enum_value": {
"$ref": "#/definitions/examplepbNumericEnum"
},
"fixed32_value": {
"type": "integer",
"format": "int32"
Expand Down Expand Up @@ -355,6 +369,14 @@
}
}
},
"examplepbNumericEnum": {
"type": "string",
"enum": [
"ZERO",
"ONE"
],
"default": "ZERO"
},
"subStringMessage": {
"properties": {
"value": {
Expand Down
58 changes: 56 additions & 2 deletions protoc-gen-grpc-gateway/descriptor/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ type Registry struct {
// msgs is a mapping from fully-qualified message name to descriptor
msgs map[string]*Message

// enums is a mapping from fully-qualified enum name to descriptor
enums map[string]*Enum

// files is a mapping from file path to descriptor
files map[string]*File

Expand All @@ -33,13 +36,14 @@ type Registry struct {
func NewRegistry() *Registry {
return &Registry{
msgs: make(map[string]*Message),
enums: make(map[string]*Enum),
files: make(map[string]*File),
pkgMap: make(map[string]string),
pkgAliases: make(map[string]string),
}
}

// Load loads definitions of services, methods, messages and fields from "req".
// Load loads definitions of services, methods, messages, enumerations and fields from "req".
func (r *Registry) Load(req *plugin.CodeGeneratorRequest) error {
for _, file := range req.GetProtoFile() {
r.loadFile(file)
Expand Down Expand Up @@ -67,7 +71,7 @@ func (r *Registry) Load(req *plugin.CodeGeneratorRequest) error {
return nil
}

// loadFile loads messages and fiels from "file".
// loadFile loads messages, enumerations and fields from "file".
// It does not loads services and methods in "file". You need to call
// loadServices after loadFiles is called for all files to load services and methods.
func (r *Registry) loadFile(file *descriptor.FileDescriptorProto) {
Expand All @@ -91,6 +95,7 @@ func (r *Registry) loadFile(file *descriptor.FileDescriptorProto) {

r.files[file.GetName()] = f
r.registerMsg(f, nil, file.GetMessageType())
r.registerEnum(f, nil, file.GetEnumType())
}

func (r *Registry) registerMsg(file *File, outerPath []string, msgs []*descriptor.DescriptorProto) {
Expand All @@ -114,6 +119,20 @@ func (r *Registry) registerMsg(file *File, outerPath []string, msgs []*descripto
outers = append(outers, outerPath...)
outers = append(outers, m.GetName())
r.registerMsg(file, outers, m.GetNestedType())
r.registerEnum(file, outers, m.GetEnumType())
}
}

func (r *Registry) registerEnum(file *File, outerPath []string, enums []*descriptor.EnumDescriptorProto) {
for _, ed := range enums {
e := &Enum{
File: file,
Outers: outerPath,
EnumDescriptorProto: ed,
}
file.Enums = append(file.Enums, e)
r.enums[e.FQEN()] = e
glog.V(1).Infof("register enum name: %s", e.FQEN())
}
}

Expand Down Expand Up @@ -143,6 +162,32 @@ func (r *Registry) LookupMsg(location, name string) (*Message, error) {
return nil, fmt.Errorf("no message found: %s", name)
}

// LookupEnum looks up a enum type by "name".
// It tries to resolve "name" from "location" if "name" is a relative enum name.
func (r *Registry) LookupEnum(location, name string) (*Enum, error) {
glog.V(1).Infof("lookup enum %s from %s", name, location)
if strings.HasPrefix(name, ".") {
e, ok := r.enums[name]
if !ok {
return nil, fmt.Errorf("no enum found: %s", name)
}
return e, nil
}

if !strings.HasPrefix(location, ".") {
location = fmt.Sprintf(".%s", location)
}
components := strings.Split(location, ".")
for len(components) > 0 {
fqen := strings.Join(append(components, name), ".")
if e, ok := r.enums[fqen]; ok {
return e, nil
}
components = components[:len(components)-1]
}
return nil, fmt.Errorf("no enum found: %s", name)
}

// LookupFile looks up a file by name.
func (r *Registry) LookupFile(name string) (*File, error) {
f, ok := r.files[name]
Expand Down Expand Up @@ -197,6 +242,15 @@ func (r *Registry) GetAllFQMNs() []string {
return keys
}

// GetAllFQENs returns a list of all FQENs
func (r *Registry) GetAllFQENs() []string {
var keys []string
for k := range r.enums {
keys = append(keys, k)
}
return keys
}

// defaultGoPackageName returns the default go package name to be used for go files generated from "f".
// You might need to use an unique alias for the package when you import it. Use ReserveGoPackageAlias to get a unique alias.
func defaultGoPackageName(f *descriptor.FileDescriptorProto) string {
Expand Down
22 changes: 22 additions & 0 deletions protoc-gen-grpc-gateway/descriptor/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ type File struct {
GoPkg GoPackage
// Messages is the list of messages defined in this file.
Messages []*Message
// Enums is the list of enums defined in this file.
Enums []*Enum
// Services is the list of services defined in this file.
Services []*Service
}
Expand Down Expand Up @@ -88,6 +90,26 @@ func (m *Message) GoType(currentPackage string) string {
return fmt.Sprintf("%s.%s", pkg, name)
}

// Enum describes a protocol buffer enum types
type Enum struct {
// File is the file where the enum is defined
File *File
// Outers is a list of outer messages if this enum is a nested type.
Outers []string
*descriptor.EnumDescriptorProto
}

// FQEN returns a fully qualified enum name of this enum.
func (e *Enum) FQEN() string {
components := []string{""}
if e.File.Package != nil {
components = append(components, e.File.GetPackage())
}
components = append(components, e.Outers...)
components = append(components, e.GetName())
return strings.Join(components, ".")
}

// Service wraps descriptor.ServiceDescriptorProto for richer features.
type Service struct {
// File is the file where this service is defined.
Expand Down
Loading

0 comments on commit 4ce23d2

Please sign in to comment.