func wrapImported(file *descriptor.FileDescriptorProto, fileMap map[string]*FileDescriptor) (sl []*ImportedDescriptor) {
	for _, index := range file.PublicDependency {
		df := fileMap[file.Dependency[index]]
		for _, d := range df.Descriptors {
			if d.GetOptions().GetMapEntry() {
				continue
			}
			sl = append(sl, &ImportedDescriptor{common{file}, d})
		}
		for _, e := range df.Enums {
			sl = append(sl, &ImportedDescriptor{common{file}, e})
		}
		for _, ext := range df.Extensions {
			sl = append(sl, &ImportedDescriptor{common{file}, ext})
		}
	}
	return
}
Return a slice of all the types that are publicly imported into this file.
package protogen
import (
	"fmt"
	"log"
	"path"
	"strconv"
	"strings"
	"github.com/golang/protobuf/protoc-gen-go/descriptor"
	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
	"github.com/twitchtv/protogen/stringutils"
)
func WrapTypes(req *plugin.CodeGeneratorRequest) (genFiles, allFiles []*FileDescriptor, allFilesByName map[string]*FileDescriptor, err error) {
	allFiles = make([]*FileDescriptor, 0, len(req.ProtoFile))
	allFilesByName = make(map[string]*FileDescriptor, len(allFiles))
	for _, f := range req.ProtoFile {
		descs := wrapDescriptors(f)
		if err := buildNestedDescriptors(descs); err != nil {
			return nil, nil, nil, err
		}
		enums := wrapEnumDescriptors(f, descs)
		if err := buildNestedEnums(descs, enums); err != nil {
			return nil, nil, nil, err
		}
		exts := wrapExtensions(f)
		svcs := wrapServices(f)
		fd := &FileDescriptor{
			FileDescriptorProto: f,
			Services:            svcs,
			Descriptors:         descs,
			Enums:               enums,
			Extensions:          exts,
			proto3:              fileIsProto3(f),
		}
		extractComments(fd)
		allFiles = append(allFiles, fd)
		allFilesByName[f.GetName()] = fd
	}
	for _, fd := range allFiles {
		fd.Imported = wrapImported(fd.FileDescriptorProto, allFilesByName)
	}
	genFiles = make([]*FileDescriptor, 0, len(req.FileToGenerate))
	for _, fileName := range req.FileToGenerate {
		fd := allFilesByName[fileName]
		if fd == nil {
			err = fmt.Errorf("could not find file named %s", fileName)
			return nil, nil, nil, err
		}
		fd.Index = len(genFiles)
		genFiles = append(genFiles, fd)
	}
	return genFiles, allFiles, allFilesByName, nil
}
type common struct {
	file *descriptor.FileDescriptorProto  
}
func (c *common) File() *descriptor.FileDescriptorProto { return c.file }
func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
	return file.GetSyntax() == "proto3"
}
func (c *common) proto3() bool { return fileIsProto3(c.file) }
type Descriptor struct {
	common
	*descriptor.DescriptorProto
	Parent   *Descriptor             
	nested   []*Descriptor           
	enums    []*EnumDescriptor       
	ext      []*ExtensionDescriptor  
	typename []string                
	index    int                     
	path     string                  
	group    bool
}
func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor {
	d := &Descriptor{
		common:          common{file},
		DescriptorProto: desc,
		Parent:          parent,
		index:           index,
	}
	if parent == nil {
		d.path = fmt.Sprintf("%d,%d", messagePath, index)
	} else {
		d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
	}
	if parent != nil {
		parts := d.TypeName()
		if file.Package != nil {
			parts = append([]string{*file.Package}, parts...)
		}
		exp := "." + strings.Join(parts, ".")
		for _, field := range parent.Field {
			if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
				d.group = true
				break
			}
		}
	}
	for _, field := range desc.Extension {
		d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
	}
	return d
}
func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
	for i, desc := range file.MessageType {
		sl = wrapThisDescriptor(sl, desc, nil, file, i)
	}
	return sl
}
func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor {
	sl = append(sl, newDescriptor(desc, parent, file, index))
	me := sl[len(sl)-1]
	for i, nested := range desc.NestedType {
		sl = wrapThisDescriptor(sl, nested, me, file, i)
	}
	return sl
}
func buildNestedDescriptors(descs []*Descriptor) error {
	for _, desc := range descs {
		if len(desc.NestedType) != 0 {
			for _, nest := range descs {
				if nest.Parent == desc {
					desc.nested = append(desc.nested, nest)
				}
			}
			if len(desc.nested) != len(desc.NestedType) {
				return fmt.Errorf("internal error: nesting failure for %s", desc.GetName())
			}
		}
	}
	return nil
}
func (d *Descriptor) TypeName() []string {
	if d.typename != nil {
		return d.typename
	}
	n := 0
	for parent := d; parent != nil; parent = parent.Parent {
		n++
	}
	s := make([]string, n, n)
	for parent := d; parent != nil; parent = parent.Parent {
		n--
		s[n] = parent.GetName()
	}
	d.typename = s
	return s
}
type EnumDescriptor struct {
	common
	*descriptor.EnumDescriptorProto
	parent   *Descriptor  
	typename []string     
	index    int          
	path     string       
}
func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor {
	ed := &EnumDescriptor{
		common:              common{file},
		EnumDescriptorProto: desc,
		parent:              parent,
		index:               index,
	}
	if parent == nil {
		ed.path = fmt.Sprintf("%d,%d", enumPath, index)
	} else {
		ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
	}
	return ed
}
func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
	for i, enum := range file.EnumType {
		sl = append(sl, newEnumDescriptor(enum, nil, file, i))
	}
	for _, nested := range descs {
		for i, enum := range nested.EnumType {
			sl = append(sl, newEnumDescriptor(enum, nested, file, i))
		}
	}
	return sl
}
func buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) error {
	for _, desc := range descs {
		if len(desc.EnumType) != 0 {
			for _, enum := range enums {
				if enum.parent == desc {
					desc.enums = append(desc.enums, enum)
				}
			}
			if len(desc.enums) != len(desc.EnumType) {
				return fmt.Errorf("internal error: enum nesting failure for %s", desc.GetName())
			}
		}
	}
	return nil
}
func (e *EnumDescriptor) TypeName() (s []string) {
	if e.typename != nil {
		return e.typename
	}
	name := e.GetName()
	if e.parent == nil {
		s = make([]string, 1)
	} else {
		pname := e.parent.TypeName()
		s = make([]string, len(pname)+1)
		copy(s, pname)
	}
	s[len(s)-1] = name
	e.typename = s
	return s
}
func (e *EnumDescriptor) prefix() string {
	if e.parent == nil {
		return stringutils.CamelCase(*e.Name) + "_"
	}
	typeName := e.TypeName()
	return stringutils.CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
}
func (e *EnumDescriptor) integerValueAsString(name string) string {
	for _, c := range e.Value {
		if c.GetName() == name {
			return fmt.Sprint(c.GetNumber())
		}
	}
	log.Fatal("cannot find value for enum constant")
	return ""
}
type ExtensionDescriptor struct {
	common
	*descriptor.FieldDescriptorProto
	parent *Descriptor  
}
func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
	var sl []*ExtensionDescriptor
	for _, field := range file.Extension {
		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
	}
	return sl
}
func (e *ExtensionDescriptor) TypeName() (s []string) {
	name := e.GetName()
	if e.parent == nil {
		s = make([]string, 1)
	} else {
		pname := e.parent.TypeName()
		s = make([]string, len(pname)+1)
		copy(s, pname)
	}
	s[len(s)-1] = name
	return s
}
func (e *ExtensionDescriptor) DescName() string {
	typeName := e.TypeName()
	for i, s := range typeName {
		typeName[i] = stringutils.CamelCase(s)
	}
	return "E_" + strings.Join(typeName, "_")
}
type ImportedDescriptor struct {
	common
	Object Object
}