protoresolve

package
v2.0.0-...-c9ae7ca Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 7, 2024 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Overview

Package protoresolve contains named types for various kinds of resolvers for use with Protobuf reflection.

Overview

The core protobuf runtime API (provided by the google.golang.org/protobuf module) accepts resolvers for a number of things, such as unmarshalling from binary, JSON, and text formats and for creating protoreflect.FileDescriptor instances from *descriptorpb.FileDescriptorProto instances. However, it uses anonymous interface types for many of these cases. This package provides named types, useful for more compact parameter and field declarations as well as type assertions.

The core protobuf runtime API also includes two resolver implementations:

When using descriptors, such that all types are dynamic, using the above two types requires double the work to register everything with both. The first must be used in order to process FileDescriptorProto instances into more useful FileDescriptor instances, and the second must be used to create a resolver that the other APIs accept.

The Registry type in this package, on the other hand, allows callers to register descriptors once, and the result can automatically be used as a type registry, too, with all dynamic types.

This package also provides functions for composition: layering resolvers such that one is tried first (the "preferred" resolver), and then others can be used if the first fails to resolve. This is useful to blend known and unknown types. (See Combine.)

You can use the Resolver interface in this package with the existing global registries (protoregistry.GlobalFiles and protoregistry.GlobalTypes) via the GlobalDescriptors value. This implements Resolver and is backed by these two global registries.

The next sections describe the taxonomy of elements in this package.

Resolvers

Named resolver interfaces make up the majority of exported elements in this package. This provides nominal types so that type declarations (like in function parameters and return types) and type assertions can be more compact and readable without requiring packages redefine their own, small named types.

There are two broad classes of resolvers: those that provide *descriptors* and those that provide *types*. A resolver that provides types is the marriage of descriptors with Go's type system and generated types. A resolver that provides types might be able to return information about generated message structs. Whereas a resolver that provides descriptors can only return message descriptors and nothing that binds that message to a Go type. The bridge between the two is the dynamicpb package, which can generate dynamic types to represent a descriptor.

In this package, resolvers that provide types generally have "Type" or "TypeResolver" in their name. The other interfaces provide descriptors.

Below are the interfaces that are expected to be used the most:

  • Resolver: This provides an interface similar to that of protoregistry.Files except that it is broader and includes typed accessors for looking up descriptors. So instead of just the generic FindDescriptorByName, it also provides FindMessageDescriptorByName.

  • FileResolver & DescriptorResolver: These two interfaces are implemented by both Resolver implementations and the protoregistry.Files. So this can be used as a parameter type, and callers of the function could provide either (or some other implementation of just the necessary methods).

  • SerializationResolver: This kind of resolver is used for marshalling and unmarshalling Protobuf data. It provides types for messages and extensions. When marshalling or unmarshalling a message to/from JSON, for example, the contents of google.protobuf.Any messages must be resolved into descriptors in order to correctly transcode the data to JSON. When unmarshalling from the Protobuf binary format, tag numbers must be resolved into field and extension descriptors in order for the data to be interpreted.

The Resolver interface implements most of the other smaller resolver interfaces that provide descriptors. And it also includes an AsTypeResolver method, so it can be converted to a resolver that provides types.

Pools

A pool is a special kind of resolver that can also be used to enumerate known elements. There are three kinds of pools:

  • FilePool: A file pool allows enumeration of all file descriptors therein.
  • ExtensionPool: An extension pool allows enumeration of all known extensions.
  • TypePool: A type pool allows enumeration of all known types -- messages, enums, and extensions.

The latter provides types; both of the former provide descriptors.

Registries

A registry is a special kind of pool that allows new entries to be registered. It is basically a mutable pool. There are two kinds of registries in this package:

  • TypeRegistry: This interface allows users to record new types. This package does not actually contain any implementations. Instead, *protoregistry.Types is the recommended implementation.
  • DescriptorRegistry: This interface allows users to record new descriptors. This package contains an implementation in the form of *Registry. It is also implemented by *protoregistry.Files.

The *Registry concrete type is a DescriptorRegistry that also provides the full API of the Resolver interface.

Helpers

This package also contains myriad helper functions related to resolving and handling descriptors. Some of them are also useful to actually implement the resolver interfaces (FindExtensionByNumber, ExtensionType, TypeNameFromURL, and TypesFromResolver). And some are adapters, wrapping types that implement one interface to also provide another (ResolverFromPool, ResolverFromPools, TypesFromDescriptorPool, and TypesFromResolver).

Index

Constants

View Source
const (
	DescriptorKindUnknown = DescriptorKind(iota)
	DescriptorKindFile
	DescriptorKindMessage
	DescriptorKindField
	DescriptorKindOneof
	DescriptorKindEnum
	DescriptorKindEnumValue
	DescriptorKindExtension
	DescriptorKindService
	DescriptorKindMethod
)

The various supported DescriptorKind values.

View Source
const (
	TypeKindMessage = TypeKind(1 << iota)
	TypeKindEnum
	TypeKindExtension

	// TypeKindsAll is a bitmask that represents all types.
	TypeKindsAll = TypeKindMessage | TypeKindEnum | TypeKindExtension
	// TypeKindsSerialization includes the kinds of types needed for serialization
	// and de-serialization: messages (for interpreting google.protobuf.Any messages)
	// and extensions. These are the same types as supported in a SerializationResolver.
	TypeKindsSerialization = TypeKindMessage | TypeKindExtension
)

The various supported TypeKind values.

Variables

View Source
var (
	// GlobalDescriptors provides a view of protoregistry.GlobalFiles and protoregistry.GlobalTypes
	// as a Resolver.
	GlobalDescriptors = ResolverFromPools(protoregistry.GlobalFiles, protoregistry.GlobalTypes)

	// ErrNotFound is a sentinel error that is returned from resolvers to indicate that the named
	// element is not known to the registry. It is the same as protoregistry.NotFound.
	ErrNotFound = protoregistry.NotFound
)

Functions

func ExtensionType

ExtensionType returns a protoreflect.ExtensionType for the given descriptor. If the given descriptor implements protoreflect.ExtensionTypeDescriptor, then the corresponding type is returned. Otherwise, a dynamic extension type is returned (created using "google.golang.org/protobuf/types/dynamicpb").

func FindDescriptorByNameInFile

func FindDescriptorByNameInFile(file protoreflect.FileDescriptor, sym protoreflect.FullName) protoreflect.Descriptor

FindDescriptorByNameInFile searches the given file for the element with the given fully-qualified name. This could be used to implement the [DescriptorResolver.FindDescriptorByName] method for a resolver that doesn't want to create an index of all descriptors. This returns nil if no element with the given name belongs to this file.

This does not perform a brute-force search of all elements to find the given name. It breaks up the given name into components and then descends the descriptor hierarchy one element at a time. If the given name does not start with the file's package, it immediately returns nil.

func FindExtensionByNumber

FindExtensionByNumber searches the given descriptor pool for the requested extension. This performs an inefficient search through all files and extensions in the pool. It returns nil if the extension is not found in the file.

func FindExtensionByNumberInFile

FindExtensionByNumberInFile searches all extension in the given file for the requested extension. It returns nil if the extension is not found in the file.

func NewNotFoundError

func NewNotFoundError[T ~string](name T) error

NewNotFoundError returns an error that wraps ErrNotFound with context indicating the given name as the element that could not be found.

The parameter is generic so that it will accept both plain strings and named string types like protoreflect.FullName.

func RangeExtensionsByMessage

func RangeExtensionsByMessage(res DescriptorPool, message protoreflect.FullName, fn func(descriptor protoreflect.ExtensionDescriptor) bool)

RangeExtensionsByMessage enumerates all extensions in the given descriptor pool that extend the given message. It stops early if the given function returns false.

func RegisterTypesInFile

func RegisterTypesInFile(file protoreflect.FileDescriptor, reg TypeRegistry, kindMask TypeKind) error

RegisterTypesInFile registers all the types (with kinds that match kindMask) with the given registry. Only the types directly in file are registered. This will result in an error if any of the types in the given file are already registered as belonging to a different file.

All types will be dynamic types, created with the "google.golang.org/protobuf/types/dynamicpb" package. The only exception is for extension descriptors that also implement protoreflect.ExtensionTypeDescriptor, in which case the corresponding extension type is used.

func RegisterTypesInFileRecursive

func RegisterTypesInFileRecursive(file protoreflect.FileDescriptor, reg TypeRegistry, kindMask TypeKind) error

RegisterTypesInFileRecursive registers all the types (with kinds that match kindMask) with the given registry, for the given file and all of its transitive dependencies (i.e. its imports, and their imports, etc.). This will result in an error if any of the types in the given file (and its dependencies) are already registered as belonging to a different file.

All types will be dynamic types, created with the "google.golang.org/protobuf/types/dynamicpb" package. The only exception is for extension descriptors that also implement protoreflect.ExtensionTypeDescriptor, in which case the corresponding extension type is used.

func RegisterTypesInFilesRecursive

func RegisterTypesInFilesRecursive(files FilePool, reg TypeRegistry, kindMask TypeKind) error

RegisterTypesInFilesRecursive registers all the types (with kinds that match kindMask) with the given registry, for all files in the given pool and their dependencies. This is essentially shorthand for this:

	var err error
	files.RangeFiles(func(file protoreflect.FileDescriptor) bool {
 		err = protoresolve.RegisterTypesInFileRecursive(file, reg, kindMask)
 		return err == nil
	})
	return err

However, the actual implementation is a little more efficient for cases where some files are imported by many other files.

All types will be dynamic types, created with the "google.golang.org/protobuf/types/dynamicpb" package. The only exception is for extension descriptors that also implement protoreflect.ExtensionTypeDescriptor, in which case the corresponding extension type is used.

func ReparseUnrecognized

func ReparseUnrecognized(msg proto.Message, resolver SerializationResolver)

ReparseUnrecognized is a helper function for re-parsing unknown fields of a message, resolving any extensions therein using the given resolver. This is particularly useful for unmarshalling FileDescriptorProto and FileDescriptorSet messages. With these messages, custom options may not be statically known by the unmarshalling program, but would be defined in the descriptor protos. So when initially unmarshalling, custom options would be left unrecognized. After unmarshalling, the resulting descriptor protos can be used to create a resolver (like using [protowrap.FromFileDescriptorSet]). That resolver can in turn be supplied to this function, to re-parse the descriptor protos, thereby recognizing and interpreting custom options therein.

func TypeNameFromURL

func TypeNameFromURL(url string) protoreflect.FullName

TypeNameFromURL extracts the fully-qualified type name from the given URL. The URL is one that could be used with a google.protobuf.Any message. The last path component is the fully-qualified name.

Types

type DependencyResolver

type DependencyResolver interface {
	FileResolver
	DescriptorResolver
}

DependencyResolver can resolve dependencies, which is needed when constructing a protoreflect.FileDescriptor from a FileDescriptorProto.

This interface is the same as protodesc.Resolver.

type DescriptorConverter

type DescriptorConverter RemoteRegistry

DescriptorConverter is a type that can be used to convert between descriptors and the other representations of types and services: google.protobuf.Type, google.protobuf.Enum, and google.protobuf.Api.

It uses a RemoteRegistry to convert the alternate representations, which may involve fetching remote types by type URL in order to create a complete representation of the transitive closure of the type or service.

See RemoteRegistry.AsDescriptorConverter.

func (*DescriptorConverter) DescriptorAsApi

func (dc *DescriptorConverter) DescriptorAsApi(sd protoreflect.ServiceDescriptor) *apipb.Api

DescriptorAsApi produces an Api message that represents the given service descriptor.

func (*DescriptorConverter) DescriptorAsEnum

func (dc *DescriptorConverter) DescriptorAsEnum(ed protoreflect.EnumDescriptor) *typepb.Enum

DescriptorAsEnum produces an Enum message that represents the given enum descriptor.

func (*DescriptorConverter) DescriptorAsType

func (dc *DescriptorConverter) DescriptorAsType(md protoreflect.MessageDescriptor) *typepb.Type

DescriptorAsType produces a Type message that represents the given message descriptor.

func (*DescriptorConverter) ToEnumDescriptor

func (dc *DescriptorConverter) ToEnumDescriptor(ctx context.Context, enum *typepb.Enum) (protoreflect.EnumDescriptor, error)

ToEnumDescriptor converts the given Enum message into an enum descriptor.

func (*DescriptorConverter) ToMessageDescriptor

func (dc *DescriptorConverter) ToMessageDescriptor(ctx context.Context, msg *typepb.Type) (protoreflect.MessageDescriptor, error)

ToMessageDescriptor converts the given Type message into a message descriptor. Since the message's fields may reference other types that are not yet known, other types may be fetched, which could warrant interruption by providing a cancellable context.

func (*DescriptorConverter) ToServiceDescriptor

func (dc *DescriptorConverter) ToServiceDescriptor(ctx context.Context, api *apipb.Api) (protoreflect.ServiceDescriptor, error)

ToServiceDescriptor converts the given Api message into a service descriptor. Since the service's referenced types may not yet be known, they may be fetched, which could warrant interruption by providing a cancellable context.

type DescriptorKind

type DescriptorKind int

DescriptorKind represents the kind of a descriptor. Unlike other descriptor-related APIs, DescriptorKind distinguishes between extension fields (DescriptorKindExtension) and "regular", non-extension fields (DescriptorKindField).

func KindOf

KindOf returns the DescriptorKind of the given descriptor d.

func (DescriptorKind) String

func (k DescriptorKind) String() string

String returns a textual representation of k.

type DescriptorPool

type DescriptorPool interface {
	FilePool
	DescriptorResolver
}

DescriptorPool is a FilePool that also functions as a DescriptorResolver.

type DescriptorRegistry

type DescriptorRegistry interface {
	DescriptorPool
	RegisterFile(protoreflect.FileDescriptor) error
}

DescriptorRegistry is a file and descriptor resolver that allows the caller to add files (and their contained descriptors) to the set of files and descriptors it can resolve.

type DescriptorResolver

type DescriptorResolver interface {
	FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error)
}

DescriptorResolver can resolve descriptors by full name.

type EnumTypeResolver

type EnumTypeResolver interface {
	FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error)
}

EnumTypeResolver can resolve enum types. An enum type includes more than just a descriptor but also refers to runtime types (which could be static types generated by the protoc-gen-go plugin).

type ErrUnexpectedType

type ErrUnexpectedType struct {
	// Only one of URL or Name will be set, depending on whether
	// the type was looked up by URL or name. These fields indicate
	// the query that resulted in a descriptor of the wrong type.
	URL  string
	Name protoreflect.FullName
	// The kind of descriptor that was expected.
	Expecting DescriptorKind
	// The kind of descriptor that was actually found.
	Actual DescriptorKind
	// Optional: the descriptor that was actually found. This may
	// be nil. If non-nil, this is the descriptor instance that
	// was resolved whose kind is Actual instead of Expecting.
	Descriptor protoreflect.Descriptor
}

ErrUnexpectedType is an error that indicates a descriptor was resolved for a given URL or name, but it is of the wrong type. So a query may have been expecting a service descriptor, for example, but instead the queried name resolved to an extension descriptor.

See NewUnexpectedTypeError.

func NewUnexpectedTypeError

func NewUnexpectedTypeError(expecting DescriptorKind, got protoreflect.Descriptor, url string) *ErrUnexpectedType

NewUnexpectedTypeError constructs a new *ErrUnexpectedType based on the given properties. The last parameter, url, is optional. If empty, the returned error will indicate that the given descriptor's full name as the query.

func (*ErrUnexpectedType) Error

func (e *ErrUnexpectedType) Error() string

Error implements the error interface.

type ExtensionPool

type ExtensionPool interface {
	ExtensionResolver
	RangeExtensionsByMessage(message protoreflect.FullName, fn func(protoreflect.ExtensionDescriptor) bool)
}

ExtensionPool is an ExtensionResolver that also allows iteration over all extensions for a message.

type ExtensionResolver

type ExtensionResolver interface {
	FindExtensionByName(protoreflect.FullName) (protoreflect.ExtensionDescriptor, error)
	FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionDescriptor, error)
}

ExtensionResolver can resolve extensions based on the containing message name and field number.

type ExtensionTypeResolver

type ExtensionTypeResolver interface {
	FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
	FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
}

ExtensionTypeResolver can resolve extension types. An extension type includes more than just a descriptor but also refers to runtime types (which could be static types generated by the protoc-gen-go plugin).

This interface is the same as protoregistry.ExtensionTypeResolver.

type FilePool

type FilePool interface {
	FileResolver
	NumFiles() int
	RangeFiles(fn func(protoreflect.FileDescriptor) bool)
	NumFilesByPackage(name protoreflect.FullName) int
	RangeFilesByPackage(name protoreflect.FullName, fn func(protoreflect.FileDescriptor) bool)
}

FilePool is a FileResolver that also allows iteration over the known file descriptors.

type FileResolver

type FileResolver interface {
	FindFileByPath(string) (protoreflect.FileDescriptor, error)
}

FileResolver can resolve file descriptors by path.

type MessageResolver

type MessageResolver interface {
	FindMessageByName(protoreflect.FullName) (protoreflect.MessageDescriptor, error)
	FindMessageByURL(url string) (protoreflect.MessageDescriptor, error)
}

MessageResolver can resolve messages based on their name or a type URL. URLs must include the fully-qualified type name as the last URI path component.

type MessageTypeResolver

type MessageTypeResolver interface {
	FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error)
	FindMessageByURL(url string) (protoreflect.MessageType, error)
}

MessageTypeResolver can resolve message types. A message type includes more than just a descriptor but also refers to runtime types (which could be static types generated by the protoc-gen-go plugin).

This interface is the same as protoregistry.MessageTypeResolver.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry implements the full Resolver interface defined in this package. It is thread-safe and can be used for all kinds of operations where types or descriptors may need to be resolved from names or numbers.

func FromFiles

func FromFiles(files *protoregistry.Files) (*Registry, error)

FromFiles returns a new registry that wraps the given files. After creating this registry, callers should not directly use files -- most especially, they should not register any additional descriptors with files and should instead use the RegisterFile method of the returned registry.

This may return an error if the given files includes conflicting extension definitions (i.e. more than one extension for the same extended message and tag number).

If protoregistry.GlobalFiles is supplied, a deep copy is made first. To avoid such a copy, use GlobalDescriptors instead.

func (*Registry) AsTypePool

func (r *Registry) AsTypePool() TypePool

AsTypePool returns a view of this registry as a TypePool. This offers more methods than AsTypeResolver, providing the ability to enumerate types.

func (*Registry) AsTypeResolver

func (r *Registry) AsTypeResolver() TypeResolver

AsTypeResolver implements part of the Resolver interface.

func (*Registry) FindDescriptorByName

func (r *Registry) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error)

FindDescriptorByName implements part of the Resolver interface.

func (*Registry) FindEnumByName

func (r *Registry) FindEnumByName(name protoreflect.FullName) (protoreflect.EnumDescriptor, error)

FindEnumByName implements part of the Resolver interface.

func (*Registry) FindEnumValueByName

func (r *Registry) FindEnumValueByName(name protoreflect.FullName) (protoreflect.EnumValueDescriptor, error)

FindEnumValueByName implements part of the Resolver interface.

func (*Registry) FindExtensionByName

func (r *Registry) FindExtensionByName(name protoreflect.FullName) (protoreflect.ExtensionDescriptor, error)

FindExtensionByName implements part of the Resolver interface.

func (*Registry) FindExtensionByNumber

func (r *Registry) FindExtensionByNumber(message protoreflect.FullName, fieldNumber protoreflect.FieldNumber) (protoreflect.ExtensionDescriptor, error)

FindExtensionByNumber implements part of the Resolver interface.

func (*Registry) FindFieldByName

func (r *Registry) FindFieldByName(name protoreflect.FullName) (protoreflect.FieldDescriptor, error)

FindFieldByName implements part of the Resolver interface.

func (*Registry) FindFileByPath

func (r *Registry) FindFileByPath(path string) (protoreflect.FileDescriptor, error)

FindFileByPath implements part of the Resolver interface.

func (*Registry) FindMessageByName

func (r *Registry) FindMessageByName(name protoreflect.FullName) (protoreflect.MessageDescriptor, error)

FindMessageByName implements part of the Resolver interface.

func (*Registry) FindMessageByURL

func (r *Registry) FindMessageByURL(url string) (protoreflect.MessageDescriptor, error)

FindMessageByURL implements part of the Resolver interface.

func (*Registry) FindMethodByName

func (r *Registry) FindMethodByName(name protoreflect.FullName) (protoreflect.MethodDescriptor, error)

FindMethodByName implements part of the Resolver interface.

func (*Registry) FindOneofByName

func (r *Registry) FindOneofByName(name protoreflect.FullName) (protoreflect.OneofDescriptor, error)

FindOneofByName implements part of the Resolver interface.

func (*Registry) FindServiceByName

func (r *Registry) FindServiceByName(name protoreflect.FullName) (protoreflect.ServiceDescriptor, error)

FindServiceByName implements part of the Resolver interface.

func (*Registry) NumFiles

func (r *Registry) NumFiles() int

NumFiles implements part of the FilePool interface.

func (*Registry) NumFilesByPackage

func (r *Registry) NumFilesByPackage(name protoreflect.FullName) int

NumFilesByPackage implements part of the FilePool interface.

func (*Registry) RangeExtensionsByMessage

func (r *Registry) RangeExtensionsByMessage(message protoreflect.FullName, fn func(protoreflect.ExtensionDescriptor) bool)

RangeExtensionsByMessage implements part of the Resolver interface.

func (*Registry) RangeFiles

func (r *Registry) RangeFiles(fn func(protoreflect.FileDescriptor) bool)

RangeFiles implements part of the FilePool interface.

func (*Registry) RangeFilesByPackage

func (r *Registry) RangeFilesByPackage(name protoreflect.FullName, fn func(protoreflect.FileDescriptor) bool)

RangeFilesByPackage implements part of the FilePool interface.

func (*Registry) RegisterFile

func (r *Registry) RegisterFile(file protoreflect.FileDescriptor) error

RegisterFile implements part of the Resolver interface.

type RemoteRegistry

type RemoteRegistry struct {
	// The default base URL to apply when registering types without a URL and
	// when looking up types by name. The message name is prefixed with the
	// base URL to form a full type URL.
	//
	// If not specified or empty, a default of "type.googleapis.com" will be
	// used.
	//
	// If present, the PackageBaseURLMapper will be consulted first before
	// applying this default.
	DefaultBaseURL string
	// A function that provides the base URL for a given package. When types
	// are registered without a URL or looked up by name, this base URL is
	// used to construct a full type URL.
	//
	// If not specified or nil, or if it returns the empty string, the
	// DefaultBaseURL will be applied.
	PackageBaseURLMapper func(packageName protoreflect.FullName) string
	// A value that can retrieve type definitions at runtime. If non-nil,
	// this will be used to resolve types for URLs that have not been
	// explicitly registered.
	TypeFetcher TypeFetcher
	// The final fallback for resolving types. If a type URL has not been
	// explicitly registered and cannot be resolved by TypeFetcher (or
	// TypeFetcher is unset/nil), then Fallback will be used to resolve
	// the type by name.
	//
	// Fallback is also used to resolve custom options found in type
	// definitions returned from TypeFetcher.
	//
	// If not specified or nil, protoregistry.GlobalFiles will be used as
	// the fallback. To prevent any fallback from being used, set this to
	// an empty resolver, such as a new, empty Registry or
	// protoregistry.Files.
	Fallback DescriptorResolver
	// contains filtered or unexported fields
}

RemoteRegistry is a registry of types that are registered by remote URL. A RemoteRegistry can be configured with a TypeFetcher, which can be used to dynamically retrieve message definitions.

It differs from a Registry in that it only exposes a subset of the Resolver interface, focused on messages and enums, which are types which may be resolved by downloading schemas from a remote source.

This registry is intended to help resolve message type URLs in google.protobuf.Any messages.

func (*RemoteRegistry) AsDescriptorConverter

func (r *RemoteRegistry) AsDescriptorConverter() *DescriptorConverter

AsDescriptorConverter returns a view of this registry as a DescriptorConverter. The returned value may be used to convert type and service definitions from the descriptor representations to the google.protobuf.Type, google.protobuf.Enum, and google.protobuf.Service representations, and vice versa.

func (*RemoteRegistry) AsTypeResolver

func (r *RemoteRegistry) AsTypeResolver() *RemoteTypeResolver

AsTypeResolver returns a view of this registry that returns types instead of descriptors. The returned resolver implements TypeResolver

func (*RemoteRegistry) FindEnumByName

FindEnumByName has the same signature as the method of the same name in the Resolver interface.

But since finding a type definition may involve retrieving data via a TypeFetcher, it is recommended to use FindEnumByNameContext instead. Calling this version will implicitly use context.Background().

func (*RemoteRegistry) FindEnumByNameContext

func (r *RemoteRegistry) FindEnumByNameContext(ctx context.Context, name protoreflect.FullName) (protoreflect.EnumDescriptor, error)

FindEnumByNameContext finds a type definition for an enum with the given name. This function computes a URL for the given type using the logic described in URLForType and then delegates to FindEnumByURLContext.

func (*RemoteRegistry) FindEnumByURL

func (r *RemoteRegistry) FindEnumByURL(url string) (protoreflect.EnumDescriptor, error)

FindEnumByURL has a signature that is consistent with that of FindMessageByURL and is present for symmetry.

But since finding a type definition may involve retrieving data via a TypeFetcher, it is recommended to use FindEnumByURLContext instead. Calling this version will implicitly use context.Background().

func (*RemoteRegistry) FindEnumByURLContext

func (r *RemoteRegistry) FindEnumByURLContext(ctx context.Context, url string) (protoreflect.EnumDescriptor, error)

FindEnumByURLContext finds a type definition for an enum with the given type URL. This method first examines explicitly registered enum types (via RegisterEnum and RegisterEnumWithURL) and types already downloaded via the TypeFetcher. It will then use the TypeFetcher, if present, to try to download a type definition. And if fails to produce a result, the registry's Fallback is queried.

func (*RemoteRegistry) FindMessageByName

FindMessageByName has the same signature as the method of the same name in the Resolver interface.

But since finding a type definition may involve retrieving data via a TypeFetcher, it is recommended to use FindMessageByNameContext instead. Calling this version will implicitly use context.Background().

func (*RemoteRegistry) FindMessageByNameContext

func (r *RemoteRegistry) FindMessageByNameContext(ctx context.Context, name protoreflect.FullName) (protoreflect.MessageDescriptor, error)

FindMessageByNameContext finds a type definition for a message with the given name. This function computes a URL for the given type using the logic described in URLForType and then delegates to FindMessageByURLContext.

func (*RemoteRegistry) FindMessageByURL

func (r *RemoteRegistry) FindMessageByURL(url string) (protoreflect.MessageDescriptor, error)

FindMessageByURL has the same signature as the method of the same name in the Resolver interface.

But since finding a type definition may involve retrieving data via a TypeFetcher, it is recommended to use FindMessageByURLContext instead. Calling this version will implicitly use context.Background().

func (*RemoteRegistry) FindMessageByURLContext

func (r *RemoteRegistry) FindMessageByURLContext(ctx context.Context, url string) (protoreflect.MessageDescriptor, error)

FindMessageByURLContext finds a type definition for a message with the given type URL. This method first examines explicitly registered message types (via RegisterMessage and RegisterMessageWithURL) and types already downloaded via the TypeFetcher. It will then use the TypeFetcher, if present, to try to download a type definition. And if fails to produce a result, the registry's Fallback is queried.

func (*RemoteRegistry) RegisterEnum

func (r *RemoteRegistry) RegisterEnum(ed protoreflect.EnumDescriptor) error

RegisterEnum registers the given enum type. The URL that corresponds to the given type will be computed via URLForType. Also see RegisterEnumWithURL.

func (*RemoteRegistry) RegisterEnumWithURL

func (r *RemoteRegistry) RegisterEnumWithURL(ed protoreflect.EnumDescriptor, url string) error

RegisterEnumWithURL registers the given enum type with the given URL.

func (*RemoteRegistry) RegisterMessage

func (r *RemoteRegistry) RegisterMessage(md protoreflect.MessageDescriptor) error

RegisterMessage registers the given message type. The URL that corresponds to the given type will be computed via URLForType. Also see RegisterMessageWithURL.

func (*RemoteRegistry) RegisterMessageWithURL

func (r *RemoteRegistry) RegisterMessageWithURL(md protoreflect.MessageDescriptor, url string) error

RegisterMessageWithURL registers the given message type with the given URL.

func (*RemoteRegistry) RegisterPackageBaseURL

func (r *RemoteRegistry) RegisterPackageBaseURL(pkgName protoreflect.FullName, baseURL string, includeSubPackages bool) (string, bool)

RegisterPackageBaseURL registers the given base URL to be used with elements in the given package. If includeSubPackages is true, this base URL will also be applied to all sub-packages (unless overridden via separate call to RegisterPackageBaseURL for a particular sub-package).

func (*RemoteRegistry) RegisterTypesInFile

func (r *RemoteRegistry) RegisterTypesInFile(fd protoreflect.FileDescriptor) error

RegisterTypesInFile registers all message and enum types present in the given file. The base URL used for all types will be computed based on explicit base URL registrations, then the registry's PackageBaseURLMapper (if present), and finally the registry's DefaultBaseURL.

func (*RemoteRegistry) RegisterTypesInFileWithBaseURL

func (r *RemoteRegistry) RegisterTypesInFileWithBaseURL(fd protoreflect.FileDescriptor, baseURL string) error

RegisterTypesInFileWithBaseURL registers all message and enum types present in the given file. The given base URL is used to construct the URLs for all types.

func (*RemoteRegistry) URLForType

func (r *RemoteRegistry) URLForType(desc protoreflect.Descriptor) string

URLForType computes the type URL for the given descriptor. If the given type has been explicitly registered or has been fetched by this registry (via configured TypeFetcher), this will return the URL that was associated with the type. Otherwise, this will compute a URL for the type. Computing the URL will first look at explicitly registered package base URLs, then the registry's PackageBaseURLMapper (if configured), and finally the registry's DefaultBaseURL (if configured).

type RemoteTypeResolver

type RemoteTypeResolver RemoteRegistry

RemoteTypeResolver is an implementation of TypeResolver that uses a RemoteRegistry to resolve symbols.

All message and enum types returned will be dynamic types, created using the dynamicpb package, built on the descriptors resolved by the backing RemoteRegistry.

func (*RemoteTypeResolver) FindEnumByName

FindEnumByName implements the method of the same name on the TypeResolver interface. Since finding an enum may incur fetching the definition via a TypeFetcher, it is recommended, where possible, to instead use FindEnumByNameContext. Calling this version will implicitly use context.Background().

func (*RemoteTypeResolver) FindEnumByNameContext

func (r *RemoteTypeResolver) FindEnumByNameContext(ctx context.Context, name protoreflect.FullName) (protoreflect.EnumType, error)

FindEnumByNameContext finds an enum by name, using the given context if necessary to fetch the message type via a TypeFetcher. This uses the underlying RemoteRegistry's method of the same name.

func (*RemoteTypeResolver) FindEnumByURL

func (r *RemoteTypeResolver) FindEnumByURL(url string) (protoreflect.EnumType, error)

FindEnumByURL has a signature that is consistent with that of FindMessageByURL and is present for symmetry. Since finding an enum may incur fetching the definition via a TypeFetcher, it is recommended, where possible, to instead use FindEnumByURLContext. Calling this version will implicitly use context.Background().

func (*RemoteTypeResolver) FindEnumByURLContext

func (r *RemoteTypeResolver) FindEnumByURLContext(ctx context.Context, url string) (protoreflect.EnumType, error)

FindEnumByURLContext finds an enum by type URL, using the given context if necessary to fetch the message type via a TypeFetcher. This uses the underlying RemoteRegistry's method of the same name.

func (*RemoteTypeResolver) FindExtensionByName

func (r *RemoteTypeResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)

FindExtensionByName implements the SerializationResolver interface.

This method relies on the underlying RemoteRegistry's fallback resolver. If the registry's fallback resolver is unconfigured or nil, then protoregistry.GlobalTypes will be used to find the extension. Otherwise, if the fallback has a method named AsTypeResolver that returns a TypeResolver, it will be invoked and the resulting type resolver will be used to find the extension type. Failing all of the above, the fallback's FindDescriptorByName method will be used to find the extension. In this case the returned extension type may be a dynamic extension type, created using the dynamicpb package.

func (*RemoteTypeResolver) FindExtensionByNumber

FindExtensionByNumber implements the SerializationResolver interface.

This method relies on the underlying RemoteRegistry's fallback resolver. If the registry's fallback resolver is unconfigured or nil, then protoregistry.GlobalTypes will be used to find the extension. Otherwise, if the fallback has a method named AsTypeResolver that returns a TypeResolver, it will be invoked and the resulting type resolver will be used to find the extension type. Failing all of the above, the extension can only be found if the fallback resolver implements DescriptorPool or ExtensionResolver and will otherwise return ErrNotFound.

func (*RemoteTypeResolver) FindMessageByName

func (r *RemoteTypeResolver) FindMessageByName(name protoreflect.FullName) (protoreflect.MessageType, error)

FindMessageByName implements the SerializationResolver interface. Since finding a message may incur fetching the definition via a TypeFetcher, it is recommended, where possible, to instead use FindMessageByNameContext. Calling this version will implicitly use context.Background().

func (*RemoteTypeResolver) FindMessageByNameContext

func (r *RemoteTypeResolver) FindMessageByNameContext(ctx context.Context, name protoreflect.FullName) (protoreflect.MessageType, error)

FindMessageByNameContext finds a message by name, using the given context if necessary to fetch the message type via a TypeFetcher. This uses the underlying RemoteRegistry's method of the same name.

func (*RemoteTypeResolver) FindMessageByURL

func (r *RemoteTypeResolver) FindMessageByURL(url string) (protoreflect.MessageType, error)

FindMessageByURL implements the SerializationResolver interface. Since finding a message may incur fetching the definition via a TypeFetcher, it is recommended, where possible, to instead use FindMessageByURLContext. Calling this version will implicitly use context.Background().

func (*RemoteTypeResolver) FindMessageByURLContext

func (r *RemoteTypeResolver) FindMessageByURLContext(ctx context.Context, url string) (protoreflect.MessageType, error)

FindMessageByURLContext finds a message by type URL, using the given context if necessary to fetch the message type via a TypeFetcher. This uses the underlying RemoteRegistry's method of the same name.

type Resolver

Resolver is a comprehensive resolver interface with methods for resolving all kinds of descriptors.

The AsTypeResolver method returns a view of the resolver as a TypeResolver. In most cases, the returned types will be dynamic types constructed using the resolver's descriptors and the google.golang.org/protobuf/types/dynamicpb package.

func Combine

func Combine(res ...Resolver) Resolver

Combine returns a resolver that iterates through the given resolvers to find elements. The first resolver given is the first one checked, so will always be the preferred resolver. When that returns a protoregistry.NotFound error, the next resolver will be checked, and so on.

The NumFiles and NumFilesByPackage methods only return the number of files reported by the first resolver. (Computing an accurate number of files across all resolvers could be an expensive operation.) However, RangeFiles and RangeFilesByPackage do return files across all resolvers. They emit files for the first resolver first. If any subsequent resolver contains duplicates, they are suppressed such that the callback will only ever be invoked once for a given file path.

func ResolverFromPool

func ResolverFromPool(pool DescriptorPool) Resolver

ResolverFromPool implements the full Resolver interface on top of the given DescriptorPool. This can be used to upgrade a *protoregistry.Files to the Resolver interface. The AsTypeResolver method uses TypesFromResolver, so it returns dynamic types.

See also ResolverFromPools.

func ResolverFromPools

func ResolverFromPools(descPool DescriptorPool, typePool TypePool) Resolver

ResolverFromPools (plural) is just like ResolverFromPool (singular) except it also accepts a TypePool that is used to implement the AsTypeResolver method. So instead of always returning dynamic types based on the given DescriptorPool, it uses the given TypePool.

type SerializationResolver

type SerializationResolver interface {
	ExtensionTypeResolver
	MessageTypeResolver
}

SerializationResolver is a named interface that can be used as a resolver for various marshalling and unmarshalling operations. For example it can be used to recognize extensions when unmarshalling the binary format. And it can be used for recognizing extensions and the contents of Any messages when marshalling and unmarshalling the JSON and text formats.

This type can be assigned to the following fields:

  • proto.UnmarshalOptions.resolver
  • protojson.MarshalOptions.resolver
  • protojson.UnmarshalOptions.resolver
  • prototext.MarshalOptions.resolver
  • prototext.UnmarshalOptions.resolver

type TypeContainer

type TypeContainer interface {
	Messages() protoreflect.MessageDescriptors
	Enums() protoreflect.EnumDescriptors
	Extensions() protoreflect.ExtensionDescriptors
}

TypeContainer is a descriptor that contains types. Both protoreflect.FileDescriptor and protoreflect.MessageDescriptor can contain types so both satisfy this interface.

type TypeFetcher

type TypeFetcher interface {
	// FetchMessageType fetches the definition of a message type that is identified
	// by the given URL.
	FetchMessageType(ctx context.Context, url string) (*typepb.Type, error)
	// FetchEnumType fetches the definition of an enum type that is identified by
	// the given URL.
	FetchEnumType(ctx context.Context, url string) (*typepb.Enum, error)
}

TypeFetcher is a value that knows how to fetch type definitions for a URL. The type definitions are represented by google.protobuf.Type and google.protobuf.Enum messages (which were originally part of the specification for google.protobuf.Any and how such types could be resolved at runtime).

func CachingTypeFetcher

func CachingTypeFetcher(fetcher TypeFetcher) TypeFetcher

CachingTypeFetcher adds a caching layer to the given type fetcher. Queries for types that have already been fetched will not result in another call to the underlying fetcher and instead are retrieved from the cache.

func HttpTypeFetcher

func HttpTypeFetcher(transport http.RoundTripper, szLimit, parLimit int) TypeFetcher

HttpTypeFetcher returns a TypeFetcher that uses the given HTTP transport to query and download type definitions. The given szLimit is the maximum response size accepted. If used from multiple goroutines (like when a type's dependency graph is resolved in parallel), this resolver limits the number of parallel queries/downloads to the given parLimit.

type TypeFetcherFunc

type TypeFetcherFunc func(ctx context.Context, url string, enum bool) (proto.Message, error)

TypeFetcherFunc is a TypeFetcher implementation backed by a single function. The function accepts a parameter to have it switch between fetching a message type vs. finding an enum type.

func (TypeFetcherFunc) FetchEnumType

func (t TypeFetcherFunc) FetchEnumType(ctx context.Context, url string) (*typepb.Enum, error)

FetchEnumType implements the TypeFetcher interface.

func (TypeFetcherFunc) FetchMessageType

func (t TypeFetcherFunc) FetchMessageType(ctx context.Context, url string) (*typepb.Type, error)

FetchMessageType implements the TypeFetcher interface.

type TypeKind

type TypeKind int

TypeKind represents a category of types that can be registered in a TypeRegistry. The value for a particular kind is a single bit, so a TypeKind value can also represent multiple kinds, by setting multiple bits (by combining values via bitwise-OR).

func (TypeKind) String

func (k TypeKind) String() string

type TypePool

type TypePool interface {
	TypeResolver
	RangeMessages(fn func(protoreflect.MessageType) bool)
	RangeEnums(fn func(protoreflect.EnumType) bool)
	RangeExtensions(fn func(protoreflect.ExtensionType) bool)
	RangeExtensionsByMessage(message protoreflect.FullName, fn func(protoreflect.ExtensionType) bool)
}

TypePool is a type resolver that allows for iteration over all known types.

func TypesFromDescriptorPool

func TypesFromDescriptorPool(pool DescriptorPool) TypePool

TypesFromDescriptorPool adapts a descriptor pool into a pool that returns types. This can be used by implementations of Resolver to implement the [Resolver.AsTypeResolver] method.

If the given resolver implements ExtensionResolver, then the returned type pool provides an efficient implementation for the [ExtensionTypeResolver.FindExtensionByNumber] method. Otherwise, it will use an inefficient implementation that searches through all files for the requested extension.

type TypeRegistry

type TypeRegistry interface {
	TypePool
	RegisterMessage(protoreflect.MessageType) error
	RegisterEnum(protoreflect.EnumType) error
	RegisterExtension(protoreflect.ExtensionType) error
}

TypeRegistry is a type resolver that allows the caller to add elements to the set of types it can resolve.

type TypeResolver

TypeResolver can resolve all types: extensions, messages, and enums.

func TypesFromResolver

func TypesFromResolver(resolver interface {
	DescriptorResolver
	ExtensionResolver
}) TypeResolver

TypesFromResolver adapts a resolver that returns descriptors into a resolver that returns types. This can be used by implementations of Resolver to implement the [Resolver.AsTypeResolver] method.

It returns all dynamic types except for extensions, in which case, if an extension implements protoreflect.ExtensionTypeDescriptor, it will return its associated protoreflect.ExtensionType. (Otherwise it returns a dynamic extension.)

type TypedDescriptorResolver

TypedDescriptorResolver can resolve descriptors by full name and provides strongly-typed methods for each kind of descriptor.

Note that FindFieldByName may return normal fields and may also return extension fields. But FindExtensionByName should only ever return extensions. If the fully-qualified name of a normal field is provided to FindExtensionByName, it should return an error indicating that the named element was the wrong kind.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL