75 lines
2.0 KiB
Go
75 lines
2.0 KiB
Go
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"compress/gzip"
|
|
"context"
|
|
"io"
|
|
"strings"
|
|
|
|
reflectionv1 "cosmossdk.io/api/cosmos/reflection/v1"
|
|
"github.com/cosmos/gogoproto/proto"
|
|
"golang.org/x/exp/slices"
|
|
protov2 "google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protodesc"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
"google.golang.org/protobuf/reflect/protoregistry"
|
|
"google.golang.org/protobuf/types/descriptorpb"
|
|
)
|
|
|
|
// ReflectionService implements the cosmos.reflection.v1 service.
|
|
type ReflectionService struct {
|
|
reflectionv1.UnimplementedReflectionServiceServer
|
|
files *descriptorpb.FileDescriptorSet
|
|
}
|
|
|
|
func NewReflectionService() (*ReflectionService, error) {
|
|
fds := &descriptorpb.FileDescriptorSet{}
|
|
|
|
// load gogo proto file descriptors
|
|
allFds := proto.AllFileDescriptors()
|
|
haveFileDescriptor := map[string]bool{}
|
|
for _, compressedBz := range allFds {
|
|
rdr, err := gzip.NewReader(bytes.NewReader(compressedBz))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
bz, err := io.ReadAll(rdr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fd := &descriptorpb.FileDescriptorProto{}
|
|
err = protov2.Unmarshal(bz, fd)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
fds.File = append(fds.File, fd)
|
|
haveFileDescriptor[*fd.Name] = true
|
|
}
|
|
|
|
// load any protoregistry file descriptors not in gogo
|
|
protoregistry.GlobalFiles.RangeFiles(func(fileDescriptor protoreflect.FileDescriptor) bool {
|
|
if !haveFileDescriptor[fileDescriptor.Path()] {
|
|
fds.File = append(fds.File, protodesc.ToFileDescriptorProto(fileDescriptor))
|
|
}
|
|
return true
|
|
})
|
|
|
|
slices.SortFunc(fds.File, func(x, y *descriptorpb.FileDescriptorProto) int {
|
|
return strings.Compare(*x.Name, *y.Name)
|
|
})
|
|
|
|
return &ReflectionService{files: fds}, nil
|
|
}
|
|
|
|
func (r ReflectionService) FileDescriptors(_ context.Context, _ *reflectionv1.FileDescriptorsRequest) (*reflectionv1.FileDescriptorsResponse, error) {
|
|
return &reflectionv1.FileDescriptorsResponse{
|
|
Files: r.files.File,
|
|
}, nil
|
|
}
|
|
|
|
var _ reflectionv1.ReflectionServiceServer = &ReflectionService{}
|