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  }