github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/fastreflection/copied/file_info.go (about) 1 package copied 2 3 import ( 4 "google.golang.org/protobuf/compiler/protogen" 5 "google.golang.org/protobuf/encoding/protowire" 6 "google.golang.org/protobuf/types/descriptorpb" 7 ) 8 9 func NewFileInfo(file *protogen.File) *FileInfo { 10 f := &FileInfo{File: file} 11 12 // Collect all enums, messages, and extensions in "flattened ordering". 13 // See filetype.TypeBuilder. 14 var walkMessages func([]*protogen.Message, func(*protogen.Message)) 15 walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) { 16 for _, m := range messages { 17 f(m) 18 walkMessages(m.Messages, f) 19 } 20 } 21 initEnumInfos := func(enums []*protogen.Enum) { 22 for _, enum := range enums { 23 f.allEnums = append(f.allEnums, newEnumInfo(f, enum)) 24 } 25 } 26 initMessageInfos := func(messages []*protogen.Message) { 27 for _, message := range messages { 28 f.allMessages = append(f.allMessages, newMessageInfo(f, message)) 29 } 30 } 31 initExtensionInfos := func(extensions []*protogen.Extension) { 32 for _, extension := range extensions { 33 f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension)) 34 } 35 } 36 initEnumInfos(f.Enums) 37 initMessageInfos(f.Messages) 38 initExtensionInfos(f.Extensions) 39 walkMessages(f.Messages, func(m *protogen.Message) { 40 initEnumInfos(m.Enums) 41 initMessageInfos(m.Messages) 42 initExtensionInfos(m.Extensions) 43 }) 44 45 // Derive a reverse mapping of enum and message pointers to their index 46 // in allEnums and allMessages. 47 if len(f.allEnums) > 0 { 48 f.allEnumsByPtr = make(map[*enumInfo]int) 49 for i, e := range f.allEnums { 50 f.allEnumsByPtr[e] = i 51 } 52 } 53 if len(f.allMessages) > 0 { 54 f.AllMessagesByPtr = make(map[*MessageInfo]int) 55 f.allMessageFieldsByPtr = make(map[*MessageInfo]*structFields) 56 for i, m := range f.allMessages { 57 f.AllMessagesByPtr[m] = i 58 f.allMessageFieldsByPtr[m] = new(structFields) 59 } 60 } 61 62 return f 63 } 64 65 type FileInfo struct { 66 *protogen.File 67 68 allEnums []*enumInfo 69 allMessages []*MessageInfo 70 allExtensions []*extensionInfo 71 72 allEnumsByPtr map[*enumInfo]int // value is index into allEnums 73 AllMessagesByPtr map[*MessageInfo]int // value is index into allMessages 74 allMessageFieldsByPtr map[*MessageInfo]*structFields 75 76 // needRawDesc specifies whether the generator should emit logic to provide 77 // the legacy raw descriptor in GZIP'd form. 78 // This is updated by enum and message generation logic as necessary, 79 // and checked at the end of file generation. 80 needRawDesc bool 81 } 82 83 type structFields struct { 84 count int 85 unexported map[int]string 86 } 87 88 type enumInfo struct { 89 *protogen.Enum 90 91 genJSONMethod bool 92 genRawDescMethod bool 93 } 94 95 func newEnumInfo(f *FileInfo, enum *protogen.Enum) *enumInfo { 96 e := &enumInfo{Enum: enum} 97 e.genJSONMethod = true 98 e.genRawDescMethod = true 99 return e 100 } 101 102 type MessageInfo struct { 103 *protogen.Message 104 105 genRawDescMethod bool 106 genExtRangeMethod bool 107 108 isTracked bool 109 hasWeak bool 110 } 111 112 func newMessageInfo(f *FileInfo, message *protogen.Message) *MessageInfo { 113 m := &MessageInfo{Message: message} 114 m.genRawDescMethod = true 115 m.genExtRangeMethod = true 116 m.isTracked = isTrackedMessage(m) 117 for _, field := range m.Fields { 118 m.hasWeak = m.hasWeak || field.Desc.IsWeak() 119 } 120 return m 121 } 122 123 // isTrackedMessage reports whether field tracking is enabled on the message. 124 func isTrackedMessage(m *MessageInfo) (tracked bool) { 125 const trackFieldUse_fieldNumber = 37383685 126 127 // Decode the option from unknown fields to avoid a dependency on the 128 // annotation proto from protoc-gen-go. 129 b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown() 130 for len(b) > 0 { 131 num, typ, n := protowire.ConsumeTag(b) 132 b = b[n:] 133 if num == trackFieldUse_fieldNumber && typ == protowire.VarintType { 134 v, _ := protowire.ConsumeVarint(b) 135 tracked = protowire.DecodeBool(v) 136 } 137 m := protowire.ConsumeFieldValue(num, typ, b) 138 b = b[m:] 139 } 140 return tracked 141 } 142 143 type extensionInfo struct { 144 *protogen.Extension 145 } 146 147 func newExtensionInfo(f *FileInfo, extension *protogen.Extension) *extensionInfo { 148 x := &extensionInfo{Extension: extension} 149 return x 150 }