| // 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) |
| } |