256
|
1 |
// Copyright 2019 The Go Authors. All rights reserved. |
|
2 |
// Use of this source code is governed by a BSD-style |
|
3 |
// license that can be found in the LICENSE file. |
|
4 |
|
|
5 |
// Package filedesc provides functionality for constructing descriptors. |
|
6 |
// |
|
7 |
// The types in this package implement interfaces in the protoreflect package |
|
8 |
// related to protobuf descripriptors. |
|
9 |
package filedesc |
|
10 |
|
|
11 |
import ( |
|
12 |
"google.golang.org/protobuf/encoding/protowire" |
|
13 |
"google.golang.org/protobuf/internal/genid" |
|
14 |
"google.golang.org/protobuf/reflect/protoreflect" |
260
|
15 |
"google.golang.org/protobuf/reflect/protoregistry" |
256
|
16 |
) |
|
17 |
|
|
18 |
// Builder construct a protoreflect.FileDescriptor from the raw descriptor. |
|
19 |
type Builder struct { |
|
20 |
// GoPackagePath is the Go package path that is invoking this builder. |
|
21 |
GoPackagePath string |
|
22 |
|
|
23 |
// RawDescriptor is the wire-encoded bytes of FileDescriptorProto |
|
24 |
// and must be populated. |
|
25 |
RawDescriptor []byte |
|
26 |
|
|
27 |
// NumEnums is the total number of enums declared in the file. |
|
28 |
NumEnums int32 |
|
29 |
// NumMessages is the total number of messages declared in the file. |
|
30 |
// It includes the implicit message declarations for map entries. |
|
31 |
NumMessages int32 |
|
32 |
// NumExtensions is the total number of extensions declared in the file. |
|
33 |
NumExtensions int32 |
|
34 |
// NumServices is the total number of services declared in the file. |
|
35 |
NumServices int32 |
|
36 |
|
|
37 |
// TypeResolver resolves extension field types for descriptor options. |
|
38 |
// If nil, it uses protoregistry.GlobalTypes. |
|
39 |
TypeResolver interface { |
260
|
40 |
protoregistry.ExtensionTypeResolver |
256
|
41 |
} |
|
42 |
|
|
43 |
// FileRegistry is use to lookup file, enum, and message dependencies. |
|
44 |
// Once constructed, the file descriptor is registered here. |
|
45 |
// If nil, it uses protoregistry.GlobalFiles. |
|
46 |
FileRegistry interface { |
|
47 |
FindFileByPath(string) (protoreflect.FileDescriptor, error) |
260
|
48 |
FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) |
|
49 |
RegisterFile(protoreflect.FileDescriptor) error |
256
|
50 |
} |
|
51 |
} |
|
52 |
|
|
53 |
// resolverByIndex is an interface Builder.FileRegistry may implement. |
|
54 |
// If so, it permits looking up an enum or message dependency based on the |
|
55 |
// sub-list and element index into filetype.Builder.DependencyIndexes. |
|
56 |
type resolverByIndex interface { |
260
|
57 |
FindEnumByIndex(int32, int32, []Enum, []Message) protoreflect.EnumDescriptor |
|
58 |
FindMessageByIndex(int32, int32, []Enum, []Message) protoreflect.MessageDescriptor |
256
|
59 |
} |
|
60 |
|
|
61 |
// Indexes of each sub-list in filetype.Builder.DependencyIndexes. |
|
62 |
const ( |
|
63 |
listFieldDeps int32 = iota |
|
64 |
listExtTargets |
|
65 |
listExtDeps |
|
66 |
listMethInDeps |
|
67 |
listMethOutDeps |
|
68 |
) |
|
69 |
|
|
70 |
// Out is the output of the Builder. |
|
71 |
type Out struct { |
260
|
72 |
File protoreflect.FileDescriptor |
256
|
73 |
|
|
74 |
// Enums is all enum descriptors in "flattened ordering". |
|
75 |
Enums []Enum |
|
76 |
// Messages is all message descriptors in "flattened ordering". |
|
77 |
// It includes the implicit message declarations for map entries. |
|
78 |
Messages []Message |
|
79 |
// Extensions is all extension descriptors in "flattened ordering". |
|
80 |
Extensions []Extension |
|
81 |
// Service is all service descriptors in "flattened ordering". |
|
82 |
Services []Service |
|
83 |
} |
|
84 |
|
|
85 |
// Build constructs a FileDescriptor given the parameters set in Builder. |
|
86 |
// It assumes that the inputs are well-formed and panics if any inconsistencies |
|
87 |
// are encountered. |
|
88 |
// |
|
89 |
// If NumEnums+NumMessages+NumExtensions+NumServices is zero, |
|
90 |
// then Build automatically derives them from the raw descriptor. |
|
91 |
func (db Builder) Build() (out Out) { |
|
92 |
// Populate the counts if uninitialized. |
|
93 |
if db.NumEnums+db.NumMessages+db.NumExtensions+db.NumServices == 0 { |
|
94 |
db.unmarshalCounts(db.RawDescriptor, true) |
|
95 |
} |
|
96 |
|
|
97 |
// Initialize resolvers and registries if unpopulated. |
|
98 |
if db.TypeResolver == nil { |
260
|
99 |
db.TypeResolver = protoregistry.GlobalTypes |
256
|
100 |
} |
|
101 |
if db.FileRegistry == nil { |
260
|
102 |
db.FileRegistry = protoregistry.GlobalFiles |
256
|
103 |
} |
|
104 |
|
|
105 |
fd := newRawFile(db) |
|
106 |
out.File = fd |
|
107 |
out.Enums = fd.allEnums |
|
108 |
out.Messages = fd.allMessages |
|
109 |
out.Extensions = fd.allExtensions |
|
110 |
out.Services = fd.allServices |
|
111 |
|
|
112 |
if err := db.FileRegistry.RegisterFile(fd); err != nil { |
|
113 |
panic(err) |
|
114 |
} |
|
115 |
return out |
|
116 |
} |
|
117 |
|
|
118 |
// unmarshalCounts counts the number of enum, message, extension, and service |
|
119 |
// declarations in the raw message, which is either a FileDescriptorProto |
|
120 |
// or a MessageDescriptorProto depending on whether isFile is set. |
|
121 |
func (db *Builder) unmarshalCounts(b []byte, isFile bool) { |
|
122 |
for len(b) > 0 { |
|
123 |
num, typ, n := protowire.ConsumeTag(b) |
|
124 |
b = b[n:] |
|
125 |
switch typ { |
|
126 |
case protowire.BytesType: |
|
127 |
v, m := protowire.ConsumeBytes(b) |
|
128 |
b = b[m:] |
|
129 |
if isFile { |
|
130 |
switch num { |
|
131 |
case genid.FileDescriptorProto_EnumType_field_number: |
|
132 |
db.NumEnums++ |
|
133 |
case genid.FileDescriptorProto_MessageType_field_number: |
|
134 |
db.unmarshalCounts(v, false) |
|
135 |
db.NumMessages++ |
|
136 |
case genid.FileDescriptorProto_Extension_field_number: |
|
137 |
db.NumExtensions++ |
|
138 |
case genid.FileDescriptorProto_Service_field_number: |
|
139 |
db.NumServices++ |
|
140 |
} |
|
141 |
} else { |
|
142 |
switch num { |
|
143 |
case genid.DescriptorProto_EnumType_field_number: |
|
144 |
db.NumEnums++ |
|
145 |
case genid.DescriptorProto_NestedType_field_number: |
|
146 |
db.unmarshalCounts(v, false) |
|
147 |
db.NumMessages++ |
|
148 |
case genid.DescriptorProto_Extension_field_number: |
|
149 |
db.NumExtensions++ |
|
150 |
} |
|
151 |
} |
|
152 |
default: |
|
153 |
m := protowire.ConsumeFieldValue(num, typ, b) |
|
154 |
b = b[m:] |
|
155 |
} |
|
156 |
} |
|
157 |
} |