podman
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.
9package filedesc10
11import (12"google.golang.org/protobuf/encoding/protowire"13"google.golang.org/protobuf/internal/genid"14"google.golang.org/protobuf/reflect/protoreflect"15"google.golang.org/protobuf/reflect/protoregistry"16)
17
18// Builder construct a protoreflect.FileDescriptor from the raw descriptor.
19type Builder struct {20// GoPackagePath is the Go package path that is invoking this builder.21GoPackagePath string22
23// RawDescriptor is the wire-encoded bytes of FileDescriptorProto24// and must be populated.25RawDescriptor []byte26
27// NumEnums is the total number of enums declared in the file.28NumEnums int3229// NumMessages is the total number of messages declared in the file.30// It includes the implicit message declarations for map entries.31NumMessages int3232// NumExtensions is the total number of extensions declared in the file.33NumExtensions int3234// NumServices is the total number of services declared in the file.35NumServices int3236
37// TypeResolver resolves extension field types for descriptor options.38// If nil, it uses protoregistry.GlobalTypes.39TypeResolver interface {40protoregistry.ExtensionTypeResolver41}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.46FileRegistry interface {47FindFileByPath(string) (protoreflect.FileDescriptor, error)48FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)49RegisterFile(protoreflect.FileDescriptor) error50}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.
56type resolverByIndex interface {57FindEnumByIndex(int32, int32, []Enum, []Message) protoreflect.EnumDescriptor58FindMessageByIndex(int32, int32, []Enum, []Message) protoreflect.MessageDescriptor59}
60
61// Indexes of each sub-list in filetype.Builder.DependencyIndexes.
62const (63listFieldDeps int32 = iota64listExtTargets
65listExtDeps
66listMethInDeps
67listMethOutDeps
68)
69
70// Out is the output of the Builder.
71type Out struct {72File protoreflect.FileDescriptor73
74// Enums is all enum descriptors in "flattened ordering".75Enums []Enum76// Messages is all message descriptors in "flattened ordering".77// It includes the implicit message declarations for map entries.78Messages []Message79// Extensions is all extension descriptors in "flattened ordering".80Extensions []Extension81// Service is all service descriptors in "flattened ordering".82Services []Service83}
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.
91func (db Builder) Build() (out Out) {92// Populate the counts if uninitialized.93if db.NumEnums+db.NumMessages+db.NumExtensions+db.NumServices == 0 {94db.unmarshalCounts(db.RawDescriptor, true)95}96
97// Initialize resolvers and registries if unpopulated.98if db.TypeResolver == nil {99db.TypeResolver = protoregistry.GlobalTypes100}101if db.FileRegistry == nil {102db.FileRegistry = protoregistry.GlobalFiles103}104
105fd := newRawFile(db)106out.File = fd107out.Enums = fd.allEnums108out.Messages = fd.allMessages109out.Extensions = fd.allExtensions110out.Services = fd.allServices111
112if err := db.FileRegistry.RegisterFile(fd); err != nil {113panic(err)114}115return out116}
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.
121func (db *Builder) unmarshalCounts(b []byte, isFile bool) {122for len(b) > 0 {123num, typ, n := protowire.ConsumeTag(b)124b = b[n:]125switch typ {126case protowire.BytesType:127v, m := protowire.ConsumeBytes(b)128b = b[m:]129if isFile {130switch num {131case genid.FileDescriptorProto_EnumType_field_number:132db.NumEnums++133case genid.FileDescriptorProto_MessageType_field_number:134db.unmarshalCounts(v, false)135db.NumMessages++136case genid.FileDescriptorProto_Extension_field_number:137db.NumExtensions++138case genid.FileDescriptorProto_Service_field_number:139db.NumServices++140}141} else {142switch num {143case genid.DescriptorProto_EnumType_field_number:144db.NumEnums++145case genid.DescriptorProto_NestedType_field_number:146db.unmarshalCounts(v, false)147db.NumMessages++148case genid.DescriptorProto_Extension_field_number:149db.NumExtensions++150}151}152default:153m := protowire.ConsumeFieldValue(num, typ, b)154b = b[m:]155}156}157}
158