| // Protocol Buffers for Go with Gadgets |
| // |
| // Copyright (c) 2013, The GoGo Authors. All rights reserved. |
| // http://github.com/gogo/protobuf |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions are |
| // met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following disclaimer |
| // in the documentation and/or other materials provided with the |
| // distribution. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| package descriptor |
| |
| import ( |
| "strings" |
| ) |
| |
| func (msg *DescriptorProto) GetMapFields() (*FieldDescriptorProto, *FieldDescriptorProto) { |
| if !msg.GetOptions().GetMapEntry() { |
| return nil, nil |
| } |
| return msg.GetField()[0], msg.GetField()[1] |
| } |
| |
| func dotToUnderscore(r rune) rune { |
| if r == '.' { |
| return '_' |
| } |
| return r |
| } |
| |
| func (field *FieldDescriptorProto) WireType() (wire int) { |
| switch *field.Type { |
| case FieldDescriptorProto_TYPE_DOUBLE: |
| return 1 |
| case FieldDescriptorProto_TYPE_FLOAT: |
| return 5 |
| case FieldDescriptorProto_TYPE_INT64: |
| return 0 |
| case FieldDescriptorProto_TYPE_UINT64: |
| return 0 |
| case FieldDescriptorProto_TYPE_INT32: |
| return 0 |
| case FieldDescriptorProto_TYPE_UINT32: |
| return 0 |
| case FieldDescriptorProto_TYPE_FIXED64: |
| return 1 |
| case FieldDescriptorProto_TYPE_FIXED32: |
| return 5 |
| case FieldDescriptorProto_TYPE_BOOL: |
| return 0 |
| case FieldDescriptorProto_TYPE_STRING: |
| return 2 |
| case FieldDescriptorProto_TYPE_GROUP: |
| return 2 |
| case FieldDescriptorProto_TYPE_MESSAGE: |
| return 2 |
| case FieldDescriptorProto_TYPE_BYTES: |
| return 2 |
| case FieldDescriptorProto_TYPE_ENUM: |
| return 0 |
| case FieldDescriptorProto_TYPE_SFIXED32: |
| return 5 |
| case FieldDescriptorProto_TYPE_SFIXED64: |
| return 1 |
| case FieldDescriptorProto_TYPE_SINT32: |
| return 0 |
| case FieldDescriptorProto_TYPE_SINT64: |
| return 0 |
| } |
| panic("unreachable") |
| } |
| |
| func (field *FieldDescriptorProto) GetKeyUint64() (x uint64) { |
| packed := field.IsPacked() |
| wireType := field.WireType() |
| fieldNumber := field.GetNumber() |
| if packed { |
| wireType = 2 |
| } |
| x = uint64(uint32(fieldNumber)<<3 | uint32(wireType)) |
| return x |
| } |
| |
| func (field *FieldDescriptorProto) GetKey3Uint64() (x uint64) { |
| packed := field.IsPacked3() |
| wireType := field.WireType() |
| fieldNumber := field.GetNumber() |
| if packed { |
| wireType = 2 |
| } |
| x = uint64(uint32(fieldNumber)<<3 | uint32(wireType)) |
| return x |
| } |
| |
| func (field *FieldDescriptorProto) GetKey() []byte { |
| x := field.GetKeyUint64() |
| i := 0 |
| keybuf := make([]byte, 0) |
| for i = 0; x > 127; i++ { |
| keybuf = append(keybuf, 0x80|uint8(x&0x7F)) |
| x >>= 7 |
| } |
| keybuf = append(keybuf, uint8(x)) |
| return keybuf |
| } |
| |
| func (field *FieldDescriptorProto) GetKey3() []byte { |
| x := field.GetKey3Uint64() |
| i := 0 |
| keybuf := make([]byte, 0) |
| for i = 0; x > 127; i++ { |
| keybuf = append(keybuf, 0x80|uint8(x&0x7F)) |
| x >>= 7 |
| } |
| keybuf = append(keybuf, uint8(x)) |
| return keybuf |
| } |
| |
| func (desc *FileDescriptorSet) GetField(packageName, messageName, fieldName string) *FieldDescriptorProto { |
| msg := desc.GetMessage(packageName, messageName) |
| if msg == nil { |
| return nil |
| } |
| for _, field := range msg.GetField() { |
| if field.GetName() == fieldName { |
| return field |
| } |
| } |
| return nil |
| } |
| |
| func (file *FileDescriptorProto) GetMessage(typeName string) *DescriptorProto { |
| for _, msg := range file.GetMessageType() { |
| if msg.GetName() == typeName { |
| return msg |
| } |
| nes := file.GetNestedMessage(msg, strings.TrimPrefix(typeName, msg.GetName()+".")) |
| if nes != nil { |
| return nes |
| } |
| } |
| return nil |
| } |
| |
| func (file *FileDescriptorProto) GetNestedMessage(msg *DescriptorProto, typeName string) *DescriptorProto { |
| for _, nes := range msg.GetNestedType() { |
| if nes.GetName() == typeName { |
| return nes |
| } |
| res := file.GetNestedMessage(nes, strings.TrimPrefix(typeName, nes.GetName()+".")) |
| if res != nil { |
| return res |
| } |
| } |
| return nil |
| } |
| |
| func (desc *FileDescriptorSet) GetMessage(packageName string, typeName string) *DescriptorProto { |
| for _, file := range desc.GetFile() { |
| if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) { |
| continue |
| } |
| for _, msg := range file.GetMessageType() { |
| if msg.GetName() == typeName { |
| return msg |
| } |
| } |
| for _, msg := range file.GetMessageType() { |
| for _, nes := range msg.GetNestedType() { |
| if nes.GetName() == typeName { |
| return nes |
| } |
| if msg.GetName()+"."+nes.GetName() == typeName { |
| return nes |
| } |
| } |
| } |
| } |
| return nil |
| } |
| |
| func (desc *FileDescriptorSet) IsProto3(packageName string, typeName string) bool { |
| for _, file := range desc.GetFile() { |
| if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) { |
| continue |
| } |
| for _, msg := range file.GetMessageType() { |
| if msg.GetName() == typeName { |
| return file.GetSyntax() == "proto3" |
| } |
| } |
| for _, msg := range file.GetMessageType() { |
| for _, nes := range msg.GetNestedType() { |
| if nes.GetName() == typeName { |
| return file.GetSyntax() == "proto3" |
| } |
| if msg.GetName()+"."+nes.GetName() == typeName { |
| return file.GetSyntax() == "proto3" |
| } |
| } |
| } |
| } |
| return false |
| } |
| |
| func (msg *DescriptorProto) IsExtendable() bool { |
| return len(msg.GetExtensionRange()) > 0 |
| } |
| |
| func (desc *FileDescriptorSet) FindExtension(packageName string, typeName string, fieldName string) (extPackageName string, field *FieldDescriptorProto) { |
| parent := desc.GetMessage(packageName, typeName) |
| if parent == nil { |
| return "", nil |
| } |
| if !parent.IsExtendable() { |
| return "", nil |
| } |
| extendee := "." + packageName + "." + typeName |
| for _, file := range desc.GetFile() { |
| for _, ext := range file.GetExtension() { |
| if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) { |
| if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) { |
| continue |
| } |
| } else { |
| if ext.GetExtendee() != extendee { |
| continue |
| } |
| } |
| if ext.GetName() == fieldName { |
| return file.GetPackage(), ext |
| } |
| } |
| } |
| return "", nil |
| } |
| |
| func (desc *FileDescriptorSet) FindExtensionByFieldNumber(packageName string, typeName string, fieldNum int32) (extPackageName string, field *FieldDescriptorProto) { |
| parent := desc.GetMessage(packageName, typeName) |
| if parent == nil { |
| return "", nil |
| } |
| if !parent.IsExtendable() { |
| return "", nil |
| } |
| extendee := "." + packageName + "." + typeName |
| for _, file := range desc.GetFile() { |
| for _, ext := range file.GetExtension() { |
| if strings.Map(dotToUnderscore, file.GetPackage()) == strings.Map(dotToUnderscore, packageName) { |
| if !(ext.GetExtendee() == typeName || ext.GetExtendee() == extendee) { |
| continue |
| } |
| } else { |
| if ext.GetExtendee() != extendee { |
| continue |
| } |
| } |
| if ext.GetNumber() == fieldNum { |
| return file.GetPackage(), ext |
| } |
| } |
| } |
| return "", nil |
| } |
| |
| func (desc *FileDescriptorSet) FindMessage(packageName string, typeName string, fieldName string) (msgPackageName string, msgName string) { |
| parent := desc.GetMessage(packageName, typeName) |
| if parent == nil { |
| return "", "" |
| } |
| field := parent.GetFieldDescriptor(fieldName) |
| if field == nil { |
| var extPackageName string |
| extPackageName, field = desc.FindExtension(packageName, typeName, fieldName) |
| if field == nil { |
| return "", "" |
| } |
| packageName = extPackageName |
| } |
| typeNames := strings.Split(field.GetTypeName(), ".") |
| if len(typeNames) == 1 { |
| msg := desc.GetMessage(packageName, typeName) |
| if msg == nil { |
| return "", "" |
| } |
| return packageName, msg.GetName() |
| } |
| if len(typeNames) > 2 { |
| for i := 1; i < len(typeNames)-1; i++ { |
| packageName = strings.Join(typeNames[1:len(typeNames)-i], ".") |
| typeName = strings.Join(typeNames[len(typeNames)-i:], ".") |
| msg := desc.GetMessage(packageName, typeName) |
| if msg != nil { |
| typeNames := strings.Split(msg.GetName(), ".") |
| if len(typeNames) == 1 { |
| return packageName, msg.GetName() |
| } |
| return strings.Join(typeNames[1:len(typeNames)-1], "."), typeNames[len(typeNames)-1] |
| } |
| } |
| } |
| return "", "" |
| } |
| |
| func (msg *DescriptorProto) GetFieldDescriptor(fieldName string) *FieldDescriptorProto { |
| for _, field := range msg.GetField() { |
| if field.GetName() == fieldName { |
| return field |
| } |
| } |
| return nil |
| } |
| |
| func (desc *FileDescriptorSet) GetEnum(packageName string, typeName string) *EnumDescriptorProto { |
| for _, file := range desc.GetFile() { |
| if strings.Map(dotToUnderscore, file.GetPackage()) != strings.Map(dotToUnderscore, packageName) { |
| continue |
| } |
| for _, enum := range file.GetEnumType() { |
| if enum.GetName() == typeName { |
| return enum |
| } |
| } |
| } |
| return nil |
| } |
| |
| func (f *FieldDescriptorProto) IsEnum() bool { |
| return *f.Type == FieldDescriptorProto_TYPE_ENUM |
| } |
| |
| func (f *FieldDescriptorProto) IsMessage() bool { |
| return *f.Type == FieldDescriptorProto_TYPE_MESSAGE |
| } |
| |
| func (f *FieldDescriptorProto) IsBytes() bool { |
| return *f.Type == FieldDescriptorProto_TYPE_BYTES |
| } |
| |
| func (f *FieldDescriptorProto) IsRepeated() bool { |
| return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REPEATED |
| } |
| |
| func (f *FieldDescriptorProto) IsString() bool { |
| return *f.Type == FieldDescriptorProto_TYPE_STRING |
| } |
| |
| func (f *FieldDescriptorProto) IsBool() bool { |
| return *f.Type == FieldDescriptorProto_TYPE_BOOL |
| } |
| |
| func (f *FieldDescriptorProto) IsRequired() bool { |
| return f.Label != nil && *f.Label == FieldDescriptorProto_LABEL_REQUIRED |
| } |
| |
| func (f *FieldDescriptorProto) IsPacked() bool { |
| return f.Options != nil && f.GetOptions().GetPacked() |
| } |
| |
| func (f *FieldDescriptorProto) IsPacked3() bool { |
| if f.IsRepeated() && f.IsScalar() { |
| if f.Options == nil || f.GetOptions().Packed == nil { |
| return true |
| } |
| return f.Options != nil && f.GetOptions().GetPacked() |
| } |
| return false |
| } |
| |
| func (m *DescriptorProto) HasExtension() bool { |
| return len(m.ExtensionRange) > 0 |
| } |