blob: 38fd45d44cda41d9ae1916120835409c700dbb48 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package protoencoding
import (
"sync"
)
import (
"google.golang.org/protobuf/reflect/protodesc"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/dynamicpb"
)
import (
"github.com/apache/dubbo-kubernetes/pkg/bufman/pkg/protodescriptor"
)
func newResolver(fileDescriptors ...protodescriptor.FileDescriptor) (Resolver, error) {
if len(fileDescriptors) == 0 {
return nil, nil
}
// TODO: handle if resolvable
files, err := protodesc.FileOptions{
AllowUnresolvable: true,
}.NewFiles(
protodescriptor.FileDescriptorSetForFileDescriptors(fileDescriptors...),
)
if err != nil {
return nil, err
}
types := &protoregistry.Types{}
var rangeErr error
files.RangeFiles(func(fileDescriptor protoreflect.FileDescriptor) bool {
if err := registerDescriptors(types, fileDescriptor); err != nil {
rangeErr = err
return false
}
return true
})
if rangeErr != nil {
return nil, rangeErr
}
return &resolver{Files: files, Types: types}, nil
}
type resolver struct {
*protoregistry.Files
*protoregistry.Types
}
type descriptorContainer interface {
Messages() protoreflect.MessageDescriptors
Enums() protoreflect.EnumDescriptors
Extensions() protoreflect.ExtensionDescriptors
}
func registerDescriptors(types *protoregistry.Types, container descriptorContainer) error {
messageDescriptors := container.Messages()
for i, messagesLen := 0, messageDescriptors.Len(); i < messagesLen; i++ {
messageDescriptor := messageDescriptors.Get(i)
if err := types.RegisterMessage(dynamicpb.NewMessageType(messageDescriptor)); err != nil {
return err
}
// nested types, too
if err := registerDescriptors(types, messageDescriptor); err != nil {
return err
}
}
enumDescriptors := container.Enums()
for i, enumsLen := 0, enumDescriptors.Len(); i < enumsLen; i++ {
enumDescriptor := enumDescriptors.Get(i)
if err := types.RegisterEnum(dynamicpb.NewEnumType(enumDescriptor)); err != nil {
return err
}
}
extensionDescriptors := container.Extensions()
for i, extensionsLen := 0, extensionDescriptors.Len(); i < extensionsLen; i++ {
extensionDescriptor := extensionDescriptors.Get(i)
if err := types.RegisterExtension(dynamicpb.NewExtensionType(extensionDescriptor)); err != nil {
return err
}
}
return nil
}
type lazyResolver struct {
fn func() (Resolver, error)
init sync.Once
resolver Resolver
err error
}
func (l *lazyResolver) maybeInit() error {
l.init.Do(func() {
l.resolver, l.err = l.fn()
})
return l.err
}
func (l *lazyResolver) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindFileByPath(path)
}
func (l *lazyResolver) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindDescriptorByName(name)
}
func (l *lazyResolver) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindEnumByName(enum)
}
func (l *lazyResolver) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindExtensionByName(field)
}
func (l *lazyResolver) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindExtensionByNumber(message, field)
}
func (l *lazyResolver) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindMessageByName(message)
}
func (l *lazyResolver) FindMessageByURL(url string) (protoreflect.MessageType, error) {
if err := l.maybeInit(); err != nil {
return nil, err
}
return l.resolver.FindMessageByURL(url)
}