// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package filedesc provides functionality for constructing descriptors. // // The types in this package implement interfaces in the protoreflect package // related to protobuf descripriptors.
package filedesc import ( ) // Builder construct a protoreflect.FileDescriptor from the raw descriptor. type Builder struct { // GoPackagePath is the Go package path that is invoking this builder. GoPackagePath string // RawDescriptor is the wire-encoded bytes of FileDescriptorProto // and must be populated. RawDescriptor []byte // NumEnums is the total number of enums declared in the file. NumEnums int32 // NumMessages is the total number of messages declared in the file. // It includes the implicit message declarations for map entries. NumMessages int32 // NumExtensions is the total number of extensions declared in the file. NumExtensions int32 // NumServices is the total number of services declared in the file. NumServices int32 // TypeResolver resolves extension field types for descriptor options. // If nil, it uses protoregistry.GlobalTypes. TypeResolver interface { protoregistry.ExtensionTypeResolver } // FileRegistry is use to lookup file, enum, and message dependencies. // Once constructed, the file descriptor is registered here. // If nil, it uses protoregistry.GlobalFiles. FileRegistry interface { FindFileByPath(string) (protoreflect.FileDescriptor, error) FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) RegisterFile(protoreflect.FileDescriptor) error } } // resolverByIndex is an interface Builder.FileRegistry may implement. // If so, it permits looking up an enum or message dependency based on the // sub-list and element index into filetype.Builder.DependencyIndexes. type resolverByIndex interface { FindEnumByIndex(int32, int32, []Enum, []Message) protoreflect.EnumDescriptor FindMessageByIndex(int32, int32, []Enum, []Message) protoreflect.MessageDescriptor } // Indexes of each sub-list in filetype.Builder.DependencyIndexes. const ( listFieldDeps int32 = iota listExtTargets listExtDeps listMethInDeps listMethOutDeps ) // Out is the output of the Builder. type Out struct { File protoreflect.FileDescriptor // Enums is all enum descriptors in "flattened ordering". Enums []Enum // Messages is all message descriptors in "flattened ordering". // It includes the implicit message declarations for map entries. Messages []Message // Extensions is all extension descriptors in "flattened ordering". Extensions []Extension // Service is all service descriptors in "flattened ordering". Services []Service } // Build constructs a FileDescriptor given the parameters set in Builder. // It assumes that the inputs are well-formed and panics if any inconsistencies // are encountered. // // If NumEnums+NumMessages+NumExtensions+NumServices is zero, // then Build automatically derives them from the raw descriptor. func ( Builder) () ( Out) { // Populate the counts if uninitialized. if .NumEnums+.NumMessages+.NumExtensions+.NumServices == 0 { .unmarshalCounts(.RawDescriptor, true) } // Initialize resolvers and registries if unpopulated. if .TypeResolver == nil { .TypeResolver = protoregistry.GlobalTypes } if .FileRegistry == nil { .FileRegistry = protoregistry.GlobalFiles } := newRawFile() .File = .Enums = .allEnums .Messages = .allMessages .Extensions = .allExtensions .Services = .allServices if := .FileRegistry.RegisterFile(); != nil { panic() } return } // unmarshalCounts counts the number of enum, message, extension, and service // declarations in the raw message, which is either a FileDescriptorProto // or a MessageDescriptorProto depending on whether isFile is set. func ( *Builder) ( []byte, bool) { for len() > 0 { , , := protowire.ConsumeTag() = [:] switch { case protowire.BytesType: , := protowire.ConsumeBytes() = [:] if { switch { case genid.FileDescriptorProto_EnumType_field_number: .NumEnums++ case genid.FileDescriptorProto_MessageType_field_number: .(, false) .NumMessages++ case genid.FileDescriptorProto_Extension_field_number: .NumExtensions++ case genid.FileDescriptorProto_Service_field_number: .NumServices++ } } else { switch { case genid.DescriptorProto_EnumType_field_number: .NumEnums++ case genid.DescriptorProto_NestedType_field_number: .(, false) .NumMessages++ case genid.DescriptorProto_Extension_field_number: .NumExtensions++ } } default: := protowire.ConsumeFieldValue(, , ) = [:] } } }