func getPackageSet(packageNameToPackage map[string]*reflectv1.Package) (*reflectv1.PackageSet, error) {
	if len(packageNameToPackage) == 0 {
		return &reflectv1.PackageSet{}, nil
	}
	packageSet := &reflectv1.PackageSet{
		Packages: make([]*reflectv1.Package, 0, len(packageNameToPackage)),
	}
	for _, pkg := range packageNameToPackage {
		packageSet.Packages = append(packageSet.Packages, pkg)
	}
	sort.Slice(packageSet.Packages, func(i int, j int) bool { return packageSet.Packages[i].Name < packageSet.Packages[j].Name })
	return packageSet, nil
}
helper for NewPackageSet
package reflect
import (
	"bytes"
	"fmt"
	"sort"
	"github.com/golang/protobuf/proto"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	reflectv1 "github.com/uber/prototool/internal/reflect/gen/uber/proto/reflect/v1"
	"github.com/uber/prototool/internal/strs"
)
func NewPackageSet(fileDescriptorSets ...*descriptor.FileDescriptorSet) (*reflectv1.PackageSet, error) {
	if len(fileDescriptorSets) == 0 {
		return &reflectv1.PackageSet{}, nil
	}
	packageNameToFileNameToFileDescriptorProto, err := getPackageNameToFileNameToFileDescriptorProto(fileDescriptorSets)
	if err != nil {
		return nil, err
	}
	packageNameToPackage, err := getBasePackageNameToPackage(packageNameToFileNameToFileDescriptorProto)
	if err != nil {
		return nil, err
	}
	if err := populateDependencies(packageNameToPackage, packageNameToFileNameToFileDescriptorProto); err != nil {
		return nil, err
	}
	for packageName, fileNameToFileDescriptorProto := range packageNameToFileNameToFileDescriptorProto {
		pkg, ok := packageNameToPackage[packageName]
		if !ok {
			return nil, fmt.Errorf("no package for name %s", packageName)
		}
		if err := populateEnums(pkg, fileNameToFileDescriptorProto); err != nil {
			return nil, err
		}
		if err := populateMessages(pkg, fileNameToFileDescriptorProto); err != nil {
			return nil, err
		}
		if err := populateServices(pkg, fileNameToFileDescriptorProto); err != nil {
			return nil, err
		}
	}
	return getPackageSet(packageNameToPackage)
}
func getPackageNameToFileNameToFileDescriptorProto(fileDescriptorSets []*descriptor.FileDescriptorSet) (map[string]map[string]*descriptor.FileDescriptorProto, error) {
	packageNameToFileNameToFileDescriptorProto := make(map[string]map[string]*descriptor.FileDescriptorProto)
	for _, fileDescriptorSet := range fileDescriptorSets {
		for _, fileDescriptorProto := range fileDescriptorSet.GetFile() {
			pkg := fileDescriptorProto.GetPackage()
			if pkg == "" {
				return nil, fmt.Errorf("no package on FileDescriptorProto")
			}
			if pkg[0] == '.' {
				return nil, fmt.Errorf("malformed package fully-qualified name %s on FileDescriptorProto %+v", pkg, fileDescriptorProto)
			}
			existingMap, ok := packageNameToFileNameToFileDescriptorProto[pkg]
			if !ok {
				existingMap = make(map[string]*descriptor.FileDescriptorProto)
				packageNameToFileNameToFileDescriptorProto[pkg] = existingMap
			}
			name := fileDescriptorProto.GetName()
			existing, ok := existingMap[name]
			if ok {
				data, err := proto.Marshal(fileDescriptorProto)
				if err != nil {
					return nil, err
				}
				existingData, err := proto.Marshal(existing)
				if err != nil {
					return nil, err
				}
				if !bytes.Equal(data, existingData) {
					return nil, fmt.Errorf("unequal FileDescriptorProtos for %s", name)
				}
			} else {
				existingMap[name] = fileDescriptorProto
			}
		}
	}
	return packageNameToFileNameToFileDescriptorProto, nil
}
func getBasePackageNameToPackage(
	packageNameToFileNameToFileDescriptorProto map[string]map[string]*descriptor.FileDescriptorProto,
) (map[string]*reflectv1.Package, error) {
	packageNameToPackage := make(map[string]*reflectv1.Package)
	for packageName := range packageNameToFileNameToFileDescriptorProto {
		packageNameToPackage[packageName] = &reflectv1.Package{
			Name: packageName,
		}
	}
	return packageNameToPackage, nil
}
func populateDependencies(
	packageNameToPackage map[string]*reflectv1.Package,
	packageNameToFileNameToFileDescriptorProto map[string]map[string]*descriptor.FileDescriptorProto,
) error {
	fileNameToPackageName, err := getFileNameToPackageName(packageNameToFileNameToFileDescriptorProto)
	if err != nil {
		return err
	}
	for packageName, fileNameTofileDescriptorProto := range packageNameToFileNameToFileDescriptorProto {
		for _, fileDescriptorProto := range fileNameTofileDescriptorProto {
			for _, depFileName := range fileDescriptorProto.GetDependency() {
				depPackageName, ok := fileNameToPackageName[depFileName]
				if !ok {
					return fmt.Errorf("no package for dep %s", depFileName)
				}
				if depPackageName != packageName {
					packageNameToPackage[packageName].DependencyNames = append(packageNameToPackage[packageName].DependencyNames, depPackageName)
				}
			}
		}
	}
	for _, pkg := range packageNameToPackage {
		if len(pkg.DependencyNames) != 0 {
			pkg.DependencyNames = strs.SortUniq(pkg.DependencyNames)
		}
	}
	return nil
}
func populateEnums(
	pkg *reflectv1.Package,
	fileNameToFileDescriptorProto map[string]*descriptor.FileDescriptorProto,
) error {
	for _, fileDescriptorProto := range fileNameToFileDescriptorProto {
		enums, err := getEnums(fileDescriptorProto.GetEnumType())
		if err != nil {
			return err
		}
		if len(enums) > 0 {
			pkg.Enums = append(pkg.Enums, enums...)
		}
	}
	sort.Slice(pkg.Enums, func(i int, j int) bool { return pkg.Enums[i].Name < pkg.Enums[j].Name })
	return nil
}
func populateMessages(
	pkg *reflectv1.Package,
	fileNameToFileDescriptorProto map[string]*descriptor.FileDescriptorProto,
) error {
	for _, fileDescriptorProto := range fileNameToFileDescriptorProto {
		messages, err := getMessages(fileDescriptorProto.GetMessageType())
		if err != nil {
			return err
		}
		if len(messages) > 0 {
			pkg.Messages = append(pkg.Messages, messages...)
		}
	}
	sort.Slice(pkg.Messages, func(i int, j int) bool { return pkg.Messages[i].Name < pkg.Messages[j].Name })
	return nil
}
func populateServices(
	pkg *reflectv1.Package,
	fileNameToFileDescriptorProto map[string]*descriptor.FileDescriptorProto,
) error {
	for _, fileDescriptorProto := range fileNameToFileDescriptorProto {
		services, err := getServices(fileDescriptorProto.GetService())
		if err != nil {
			return err
		}
		if len(services) > 0 {
			pkg.Services = append(pkg.Services, services...)
		}
	}
	sort.Slice(pkg.Services, func(i int, j int) bool { return pkg.Services[i].Name < pkg.Services[j].Name })
	return nil
}