xref: /aosp_15_r20/external/golang-protobuf/cmd/protoc-gen-go/internal_gengo/init.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage internal_gengo
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"unicode"
9*1c12ee1eSDan Willemsen	"unicode/utf8"
10*1c12ee1eSDan Willemsen
11*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/compiler/protogen"
12*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/protowire"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/types/descriptorpb"
15*1c12ee1eSDan Willemsen)
16*1c12ee1eSDan Willemsen
17*1c12ee1eSDan Willemsentype fileInfo struct {
18*1c12ee1eSDan Willemsen	*protogen.File
19*1c12ee1eSDan Willemsen
20*1c12ee1eSDan Willemsen	allEnums      []*enumInfo
21*1c12ee1eSDan Willemsen	allMessages   []*messageInfo
22*1c12ee1eSDan Willemsen	allExtensions []*extensionInfo
23*1c12ee1eSDan Willemsen
24*1c12ee1eSDan Willemsen	allEnumsByPtr         map[*enumInfo]int    // value is index into allEnums
25*1c12ee1eSDan Willemsen	allMessagesByPtr      map[*messageInfo]int // value is index into allMessages
26*1c12ee1eSDan Willemsen	allMessageFieldsByPtr map[*messageInfo]*structFields
27*1c12ee1eSDan Willemsen
28*1c12ee1eSDan Willemsen	// needRawDesc specifies whether the generator should emit logic to provide
29*1c12ee1eSDan Willemsen	// the legacy raw descriptor in GZIP'd form.
30*1c12ee1eSDan Willemsen	// This is updated by enum and message generation logic as necessary,
31*1c12ee1eSDan Willemsen	// and checked at the end of file generation.
32*1c12ee1eSDan Willemsen	needRawDesc bool
33*1c12ee1eSDan Willemsen}
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsentype structFields struct {
36*1c12ee1eSDan Willemsen	count      int
37*1c12ee1eSDan Willemsen	unexported map[int]string
38*1c12ee1eSDan Willemsen}
39*1c12ee1eSDan Willemsen
40*1c12ee1eSDan Willemsenfunc (sf *structFields) append(name string) {
41*1c12ee1eSDan Willemsen	if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
42*1c12ee1eSDan Willemsen		if sf.unexported == nil {
43*1c12ee1eSDan Willemsen			sf.unexported = make(map[int]string)
44*1c12ee1eSDan Willemsen		}
45*1c12ee1eSDan Willemsen		sf.unexported[sf.count] = name
46*1c12ee1eSDan Willemsen	}
47*1c12ee1eSDan Willemsen	sf.count++
48*1c12ee1eSDan Willemsen}
49*1c12ee1eSDan Willemsen
50*1c12ee1eSDan Willemsenfunc newFileInfo(file *protogen.File) *fileInfo {
51*1c12ee1eSDan Willemsen	f := &fileInfo{File: file}
52*1c12ee1eSDan Willemsen
53*1c12ee1eSDan Willemsen	// Collect all enums, messages, and extensions in "flattened ordering".
54*1c12ee1eSDan Willemsen	// See filetype.TypeBuilder.
55*1c12ee1eSDan Willemsen	var walkMessages func([]*protogen.Message, func(*protogen.Message))
56*1c12ee1eSDan Willemsen	walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
57*1c12ee1eSDan Willemsen		for _, m := range messages {
58*1c12ee1eSDan Willemsen			f(m)
59*1c12ee1eSDan Willemsen			walkMessages(m.Messages, f)
60*1c12ee1eSDan Willemsen		}
61*1c12ee1eSDan Willemsen	}
62*1c12ee1eSDan Willemsen	initEnumInfos := func(enums []*protogen.Enum) {
63*1c12ee1eSDan Willemsen		for _, enum := range enums {
64*1c12ee1eSDan Willemsen			f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
65*1c12ee1eSDan Willemsen		}
66*1c12ee1eSDan Willemsen	}
67*1c12ee1eSDan Willemsen	initMessageInfos := func(messages []*protogen.Message) {
68*1c12ee1eSDan Willemsen		for _, message := range messages {
69*1c12ee1eSDan Willemsen			f.allMessages = append(f.allMessages, newMessageInfo(f, message))
70*1c12ee1eSDan Willemsen		}
71*1c12ee1eSDan Willemsen	}
72*1c12ee1eSDan Willemsen	initExtensionInfos := func(extensions []*protogen.Extension) {
73*1c12ee1eSDan Willemsen		for _, extension := range extensions {
74*1c12ee1eSDan Willemsen			f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
75*1c12ee1eSDan Willemsen		}
76*1c12ee1eSDan Willemsen	}
77*1c12ee1eSDan Willemsen	initEnumInfos(f.Enums)
78*1c12ee1eSDan Willemsen	initMessageInfos(f.Messages)
79*1c12ee1eSDan Willemsen	initExtensionInfos(f.Extensions)
80*1c12ee1eSDan Willemsen	walkMessages(f.Messages, func(m *protogen.Message) {
81*1c12ee1eSDan Willemsen		initEnumInfos(m.Enums)
82*1c12ee1eSDan Willemsen		initMessageInfos(m.Messages)
83*1c12ee1eSDan Willemsen		initExtensionInfos(m.Extensions)
84*1c12ee1eSDan Willemsen	})
85*1c12ee1eSDan Willemsen
86*1c12ee1eSDan Willemsen	// Derive a reverse mapping of enum and message pointers to their index
87*1c12ee1eSDan Willemsen	// in allEnums and allMessages.
88*1c12ee1eSDan Willemsen	if len(f.allEnums) > 0 {
89*1c12ee1eSDan Willemsen		f.allEnumsByPtr = make(map[*enumInfo]int)
90*1c12ee1eSDan Willemsen		for i, e := range f.allEnums {
91*1c12ee1eSDan Willemsen			f.allEnumsByPtr[e] = i
92*1c12ee1eSDan Willemsen		}
93*1c12ee1eSDan Willemsen	}
94*1c12ee1eSDan Willemsen	if len(f.allMessages) > 0 {
95*1c12ee1eSDan Willemsen		f.allMessagesByPtr = make(map[*messageInfo]int)
96*1c12ee1eSDan Willemsen		f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
97*1c12ee1eSDan Willemsen		for i, m := range f.allMessages {
98*1c12ee1eSDan Willemsen			f.allMessagesByPtr[m] = i
99*1c12ee1eSDan Willemsen			f.allMessageFieldsByPtr[m] = new(structFields)
100*1c12ee1eSDan Willemsen		}
101*1c12ee1eSDan Willemsen	}
102*1c12ee1eSDan Willemsen
103*1c12ee1eSDan Willemsen	return f
104*1c12ee1eSDan Willemsen}
105*1c12ee1eSDan Willemsen
106*1c12ee1eSDan Willemsentype enumInfo struct {
107*1c12ee1eSDan Willemsen	*protogen.Enum
108*1c12ee1eSDan Willemsen
109*1c12ee1eSDan Willemsen	genJSONMethod    bool
110*1c12ee1eSDan Willemsen	genRawDescMethod bool
111*1c12ee1eSDan Willemsen}
112*1c12ee1eSDan Willemsen
113*1c12ee1eSDan Willemsenfunc newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
114*1c12ee1eSDan Willemsen	e := &enumInfo{Enum: enum}
115*1c12ee1eSDan Willemsen	e.genJSONMethod = true
116*1c12ee1eSDan Willemsen	e.genRawDescMethod = true
117*1c12ee1eSDan Willemsen	return e
118*1c12ee1eSDan Willemsen}
119*1c12ee1eSDan Willemsen
120*1c12ee1eSDan Willemsentype messageInfo struct {
121*1c12ee1eSDan Willemsen	*protogen.Message
122*1c12ee1eSDan Willemsen
123*1c12ee1eSDan Willemsen	genRawDescMethod  bool
124*1c12ee1eSDan Willemsen	genExtRangeMethod bool
125*1c12ee1eSDan Willemsen
126*1c12ee1eSDan Willemsen	isTracked bool
127*1c12ee1eSDan Willemsen	hasWeak   bool
128*1c12ee1eSDan Willemsen}
129*1c12ee1eSDan Willemsen
130*1c12ee1eSDan Willemsenfunc newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
131*1c12ee1eSDan Willemsen	m := &messageInfo{Message: message}
132*1c12ee1eSDan Willemsen	m.genRawDescMethod = true
133*1c12ee1eSDan Willemsen	m.genExtRangeMethod = true
134*1c12ee1eSDan Willemsen	m.isTracked = isTrackedMessage(m)
135*1c12ee1eSDan Willemsen	for _, field := range m.Fields {
136*1c12ee1eSDan Willemsen		m.hasWeak = m.hasWeak || field.Desc.IsWeak()
137*1c12ee1eSDan Willemsen	}
138*1c12ee1eSDan Willemsen	return m
139*1c12ee1eSDan Willemsen}
140*1c12ee1eSDan Willemsen
141*1c12ee1eSDan Willemsen// isTrackedMessage reports whether field tracking is enabled on the message.
142*1c12ee1eSDan Willemsenfunc isTrackedMessage(m *messageInfo) (tracked bool) {
143*1c12ee1eSDan Willemsen	const trackFieldUse_fieldNumber = 37383685
144*1c12ee1eSDan Willemsen
145*1c12ee1eSDan Willemsen	// Decode the option from unknown fields to avoid a dependency on the
146*1c12ee1eSDan Willemsen	// annotation proto from protoc-gen-go.
147*1c12ee1eSDan Willemsen	b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
148*1c12ee1eSDan Willemsen	for len(b) > 0 {
149*1c12ee1eSDan Willemsen		num, typ, n := protowire.ConsumeTag(b)
150*1c12ee1eSDan Willemsen		b = b[n:]
151*1c12ee1eSDan Willemsen		if num == trackFieldUse_fieldNumber && typ == protowire.VarintType {
152*1c12ee1eSDan Willemsen			v, _ := protowire.ConsumeVarint(b)
153*1c12ee1eSDan Willemsen			tracked = protowire.DecodeBool(v)
154*1c12ee1eSDan Willemsen		}
155*1c12ee1eSDan Willemsen		m := protowire.ConsumeFieldValue(num, typ, b)
156*1c12ee1eSDan Willemsen		b = b[m:]
157*1c12ee1eSDan Willemsen	}
158*1c12ee1eSDan Willemsen	return tracked
159*1c12ee1eSDan Willemsen}
160*1c12ee1eSDan Willemsen
161*1c12ee1eSDan Willemsentype extensionInfo struct {
162*1c12ee1eSDan Willemsen	*protogen.Extension
163*1c12ee1eSDan Willemsen}
164*1c12ee1eSDan Willemsen
165*1c12ee1eSDan Willemsenfunc newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
166*1c12ee1eSDan Willemsen	x := &extensionInfo{Extension: extension}
167*1c12ee1eSDan Willemsen	return x
168*1c12ee1eSDan Willemsen}
169