diff --git a/compiler/main.go b/compiler/main.go
index c8aaa45..568a62b 100644
--- a/compiler/main.go
+++ b/compiler/main.go
@@ -35,44 +35,35 @@
 	This plugin takes no options and the protocol buffer file syntax does
 	not yet define any options for Go, so program does no option evaluation.
 	That may change.
-
-	Not supported yet:
-		Services
 */
 
 package main
 
 import (
-	"bytes"
-	"fmt"
 	"io/ioutil"
-	"log"
 	"os"
-	"strings"
-	"unicode"
 
 	"goprotobuf.googlecode.com/hg/proto"
-	plugin "goprotobuf.googlecode.com/hg/compiler/plugin"
-	descriptor "goprotobuf.googlecode.com/hg/compiler/descriptor"
+	"goprotobuf.googlecode.com/hg/compiler/generator"
 )
 
 func main() {
 	// Begin by allocating a generator. The request and response structures are stored there
 	// so we can do error handling easily - the response structure contains the field to
 	// report failure.
-	g := NewGenerator()
+	g := generator.New()
 
 	data, err := ioutil.ReadAll(os.Stdin)
 	if err != nil {
-		g.error(err, "reading input")
+		g.Error(err, "reading input")
 	}
 
-	if err := proto.Unmarshal(data, g.request); err != nil {
-		g.error(err, "parsing input proto")
+	if err := proto.Unmarshal(data, g.Request); err != nil {
+		g.Error(err, "parsing input proto")
 	}
 
-	if len(g.request.FileToGenerate) == 0 {
-		g.fail("no files to generate")
+	if len(g.Request.FileToGenerate) == 0 {
+		g.Fail("no files to generate")
 	}
 
 	// Create a wrapped version of the Descriptors and EnumDescriptors that
@@ -85,936 +76,12 @@
 	g.GenerateAllFiles()
 
 	// Send back the results.
-	data, err = proto.Marshal(g.response)
+	data, err = proto.Marshal(g.Response)
 	if err != nil {
-		g.error(err, "failed to marshal output proto")
+		g.Error(err, "failed to marshal output proto")
 	}
 	_, err = os.Stdout.Write(data)
 	if err != nil {
-		g.error(err, "failed to write output proto")
+		g.Error(err, "failed to write output proto")
 	}
 }
-
-// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
-// a pointer to the FileDescriptorProto that represents it.  These types achieve that
-// wrapping by placing each Proto inside a struct with the pointer to its File. The
-// structs have the same names as their contents, with "Proto" removed.
-// FileDescriptor is used to store the things that it points to.
-
-// The file and package name method are common to messages and enums.
-type common struct {
-	file *descriptor.FileDescriptorProto // File this object comes from.
-}
-
-// The package name we will produce in our output.
-func (c *common) packageName() string { return uniquePackageOf(c.file) }
-
-// A message (struct).
-type Descriptor struct {
-	common
-	*descriptor.DescriptorProto
-	parent   *Descriptor            // The containing message, if any.
-	nested   []*Descriptor          // Inner messages, if any.
-	ext      []*ExtensionDescriptor // Extensions, if any.
-	typename []string               // Cached typename vector.
-}
-
-// Return the elements of the dotted type name.  The package name is not part
-// of this name.
-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] = proto.GetString(parent.Name)
-	}
-	d.typename = s
-	return s
-}
-
-// An enum. If it's at top level, its parent will be nil. Otherwise it will be
-// the descriptor of the message in which it is defined.
-type EnumDescriptor struct {
-	common
-	*descriptor.EnumDescriptorProto
-	parent   *Descriptor // The containing message, if any.
-	typename []string    // Cached typename vector.
-}
-
-// Return the elements of the dotted type name.
-func (e *EnumDescriptor) typeName() (s []string) {
-	if e.typename != nil {
-		return e.typename
-	}
-	name := proto.GetString(e.Name)
-	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
-}
-
-// Everything but the last element of the full type name, CamelCased.
-// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
-func (e *EnumDescriptor) prefix() string {
-	typeName := e.typeName()
-	ccPrefix := CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
-	if e.parent == nil {
-		// If the enum is not part of a message, the prefix is just the type name.
-		ccPrefix = CamelCase(*e.Name) + "_"
-	}
-	return ccPrefix
-}
-
-// The integer value of the named constant in this enumerated type.
-func (e *EnumDescriptor) integerValueAsString(name string) string {
-	for _, c := range e.Value {
-		if proto.GetString(c.Name) == name {
-			return fmt.Sprint(proto.GetInt32(c.Number))
-		}
-	}
-	log.Exit("cannot find value for enum constant")
-	return ""
-}
-
-// An extension. If it's at top level, its parent will be nil. Otherwise it will be
-// the descriptor of the message in which it is defined.
-type ExtensionDescriptor struct {
-	common
-	*descriptor.FieldDescriptorProto
-	parent   *Descriptor // The containing message, if any.
-}
-
-// Return the elements of the dotted type name.
-func (e *ExtensionDescriptor) typeName() (s []string) {
-	name := proto.GetString(e.Name)
-	if e.parent == nil {
-		// top-level extension
-		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
-}
-
-// A file. Includes slices of all the messages and enums defined within it.
-// Those slices are constructed by WrapTypes.
-type FileDescriptor struct {
-	*descriptor.FileDescriptorProto
-	desc []*Descriptor           // All the messages defined in this file.
-	enum []*EnumDescriptor       // All the enums defined in this file.
-	ext  []*ExtensionDescriptor  // All the top-level extensions defined in this file.
-}
-
-// The package name we'll use in the generated code to refer to this file.
-func (d *FileDescriptor) packageName() string { return uniquePackageOf(d.FileDescriptorProto) }
-
-// The package named defined in the input for this file, possibly dotted.
-func (d *FileDescriptor) originalPackageName() string {
-	return proto.GetString(d.Package)
-}
-
-// Whether the proto library needs importing.
-// This will be true if there are any enums or any extensions, or any messages with extension ranges.
-func (d *FileDescriptor) needProtoImport() bool {
-	if len(d.enum) > 0 || len(d.ext) > 0 {
-		return true
-	}
-	for _, desc := range d.desc {
-		if len(desc.ext) > 0 || len(desc.ExtensionRange) > 0 {
-			return true
-		}
-	}
-	return false
-}
-
-// Simplify some things by abstracting the abilities shared by enums and messages.
-type Object interface {
-	packageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
-	typeName() []string
-}
-
-// Each package name we generate must be unique. The package we're generating
-// gets its own name but every other package must have a unqiue name that does
-// not conflict in the code we generate.  These names are chosen globally (although
-// they don't have to be, it simplifies things to do them globally).
-func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
-	s, ok := uniquePackageName[fd]
-	if !ok {
-		log.Exit("internal error: no package name defined for", proto.GetString(fd.Name))
-	}
-	return s
-}
-
-// The type whose methods generate the output, stored in the associated response structure.
-type Generator struct {
-	bytes.Buffer
-
-	request  *plugin.CodeGeneratorRequest  // The input.
-	response *plugin.CodeGeneratorResponse // The output.
-
-	packageName      string            // What we're calling ourselves.
-	allFiles         []*FileDescriptor // All files in the tree
-	genFiles         []*FileDescriptor // Those files we will generate output for.
-	file             *FileDescriptor   // The file we are compiling now.
-	typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
-	indent           string
-}
-
-// Create a new generator and allocate the request and response protobufs.
-func NewGenerator() *Generator {
-	g := new(Generator)
-	g.request = plugin.NewCodeGeneratorRequest()
-	g.response = plugin.NewCodeGeneratorResponse()
-	return g
-}
-
-// Report problem, including an os.Error, and fail.
-func (g *Generator) error(err os.Error, msgs ...string) {
-	s := strings.Join(msgs, " ") + ":" + err.String()
-	log.Stderr("protoc-gen-go: error: ", s)
-	g.response.Error = proto.String(s)
-	os.Exit(1)
-}
-
-// Report problem and fail.
-func (g *Generator) fail(msgs ...string) {
-	s := strings.Join(msgs, " ")
-	log.Stderr("protoc-gen-go: error: ", s)
-	g.response.Error = proto.String(s)
-	os.Exit(1)
-}
-
-// If this file is in a different package, return the package name we're using for this file, plus ".".
-// Otherwise return the empty string.
-func (g *Generator) DefaultPackageName(obj Object) string {
-	pkg := obj.packageName()
-	if pkg == g.packageName {
-		return ""
-	}
-	return pkg + "."
-}
-
-// For each input file, the unique package name to use, underscored.
-var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
-
-// Set the package name for this run.  It must agree across all files being generated.
-// Also define unique package names for all imported files.
-func (g *Generator) SetPackageNames() {
-	inUse := make(map[string]bool)
-	pkg := proto.GetString(g.genFiles[0].Package)
-	g.packageName = strings.Map(DotToUnderscore, pkg)
-	inUse[pkg] = true
-	for _, f := range g.genFiles {
-		thisPkg := proto.GetString(f.Package)
-		if thisPkg != pkg {
-			g.fail("inconsistent package names:", thisPkg, pkg)
-		}
-	}
-AllFiles:
-	for _, f := range g.allFiles {
-		for _, genf := range g.genFiles {
-			if f == genf {
-				// In this package already.
-				uniquePackageName[f.FileDescriptorProto] = g.packageName
-				continue AllFiles
-			}
-		}
-		truePkg := proto.GetString(f.Package)
-		pkg := truePkg
-		for {
-			_, present := inUse[pkg]
-			if present {
-				// It's a duplicate; must rename.
-				pkg += "X"
-				continue
-			}
-			break
-		}
-		// Install it.
-		inUse[pkg] = true
-		uniquePackageName[f.FileDescriptorProto] = strings.Map(DotToUnderscore, pkg)
-	}
-}
-
-// Walk the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos and FileDescriptorProtos
-// into file-referenced objects within the Generator.  Also create the list of files
-// to generate
-func (g *Generator) WrapTypes() {
-	g.allFiles = make([]*FileDescriptor, len(g.request.ProtoFile))
-	for i, f := range g.request.ProtoFile {
-		pkg := proto.GetString(f.Package)
-		if pkg == "" {
-			g.fail(proto.GetString(f.Name), "is missing a package declaration")
-		}
-		// We must wrap the descriptors before we wrap the enums
-		descs := WrapDescriptors(f)
-		g.BuildNestedDescriptors(descs)
-		enums := WrapEnumDescriptors(f, descs)
-		exts := WrapExtensions(f)
-		g.allFiles[i] = &FileDescriptor{
-			FileDescriptorProto: f,
-			desc:                descs,
-			enum:                enums,
-			ext:                 exts,
-		}
-	}
-
-	g.genFiles = make([]*FileDescriptor, len(g.request.FileToGenerate))
-FindFiles:
-	for i, fileName := range g.request.FileToGenerate {
-		// Search the list.  This algorithm is n^2 but n is tiny.
-		for _, file := range g.allFiles {
-			if fileName == proto.GetString(file.Name) {
-				g.genFiles[i] = file
-				continue FindFiles
-			}
-		}
-		g.fail("could not find file named", fileName)
-	}
-	g.response.File = make([]*plugin.CodeGeneratorResponse_File, len(g.genFiles))
-}
-
-// Scan the descriptors in this file.  For each one, build the slice of nested descriptors
-func (g *Generator) BuildNestedDescriptors(descs []*Descriptor) {
-	for _, desc := range descs {
-		if len(desc.NestedType) != 0 {
-			desc.nested = make([]*Descriptor, len(desc.NestedType))
-			n := 0
-			for _, nest := range descs {
-				if nest.parent == desc {
-					desc.nested[n] = nest
-					n++
-				}
-			}
-			if n != len(desc.NestedType) {
-				g.fail("internal error: nesting failure for", proto.GetString(desc.Name))
-			}
-		}
-	}
-}
-
-// Construct the Descriptor and add it to the slice
-func AddDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
-	d := &Descriptor{common{file: file}, desc, parent, nil, nil, nil}
-
-	d.ext = make([]*ExtensionDescriptor, len(desc.Extension))
-	for i, field := range desc.Extension {
-		d.ext[i] = &ExtensionDescriptor{common{file: file}, field, d}
-	}
-
-	if len(sl) == cap(sl) {
-		nsl := make([]*Descriptor, len(sl), 2*len(sl))
-		copy(nsl, sl)
-		sl = nsl
-	}
-	sl = sl[0 : len(sl)+1]
-	sl[len(sl)-1] = d
-	return sl
-}
-
-// Return a slice of all the Descriptors defined within this file
-func WrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
-	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
-	for _, desc := range file.MessageType {
-		sl = WrapThisDescriptor(sl, desc, nil, file)
-	}
-	return sl
-}
-
-// Wrap this Descriptor, recursively
-func WrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*Descriptor {
-	sl = AddDescriptor(sl, desc, parent, file)
-	me := sl[len(sl)-1]
-	for _, nested := range desc.NestedType {
-		sl = WrapThisDescriptor(sl, nested, me, file)
-	}
-	return sl
-}
-
-// Construct the EnumDescriptor and add it to the slice
-func AddEnumDescriptor(sl []*EnumDescriptor, desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
-	if len(sl) == cap(sl) {
-		nsl := make([]*EnumDescriptor, len(sl), 2*len(sl))
-		copy(nsl, sl)
-		sl = nsl
-	}
-	sl = sl[0 : len(sl)+1]
-	sl[len(sl)-1] = &EnumDescriptor{common{file: file}, desc, parent, nil}
-	return sl
-}
-
-// Return a slice of all the EnumDescriptors defined within this file
-func WrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
-	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
-	for _, enum := range file.EnumType {
-		sl = AddEnumDescriptor(sl, enum, nil, file)
-	}
-	for _, nested := range descs {
-		sl = WrapEnumDescriptorsInMessage(sl, nested, file)
-	}
-	return sl
-}
-
-// Wrap this EnumDescriptor, recursively
-func WrapEnumDescriptorsInMessage(sl []*EnumDescriptor, desc *Descriptor, file *descriptor.FileDescriptorProto) []*EnumDescriptor {
-	for _, enum := range desc.EnumType {
-		sl = AddEnumDescriptor(sl, enum, desc, file)
-	}
-	for _, nested := range desc.nested {
-		sl = WrapEnumDescriptorsInMessage(sl, nested, file)
-	}
-	return sl
-}
-
-// Return a slice of all the top-level ExtensionDescriptors defined within this file.
-func WrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
-	sl := make([]*ExtensionDescriptor, len(file.Extension))
-	for i, field := range file.Extension {
-		sl[i] = &ExtensionDescriptor{common{file: file}, field, nil}
-	}
-	return sl
-}
-
-// Build the map from fully qualified type names to objects.  The key for the map
-// comes from the input data, which puts a period at the beginning.
-func (g *Generator) BuildTypeNameMap() {
-	g.typeNameToObject = make(map[string]Object)
-	for _, f := range g.allFiles {
-		dottedPkg := "." + f.originalPackageName() + "."
-		for _, enum := range f.enum {
-			name := dottedPkg + DottedSlice(enum.typeName())
-			g.typeNameToObject[name] = enum
-		}
-		for _, desc := range f.desc {
-			name := dottedPkg + DottedSlice(desc.typeName())
-			g.typeNameToObject[name] = desc
-		}
-	}
-}
-
-// Given a fully-qualified input type name, return the descriptor for the message or enum with that type.
-func (g *Generator) objectNamed(typeName string) Object {
-	f, ok := g.typeNameToObject[typeName]
-	if !ok {
-		g.fail("can't find object with type", typeName)
-	}
-	return f
-}
-
-// Print the arguments, handling indirections because they may be *string, etc.
-func (g *Generator) p(str ...interface{}) {
-	g.WriteString(g.indent)
-	for _, v := range str {
-		switch s := v.(type) {
-		case string:
-			g.WriteString(s)
-		case *string:
-			g.WriteString(*s)
-		case *int32:
-			g.WriteString(fmt.Sprintf("%d", *s))
-		default:
-			g.fail(fmt.Sprintf("unknown type in printer: %T", v))
-		}
-	}
-	g.WriteByte('\n')
-}
-
-// Indent the output one tab stop.
-func (g *Generator) in() { g.indent += "\t" }
-
-// Unindent the output one tab stop.
-func (g *Generator) out() {
-	if len(g.indent) > 0 {
-		g.indent = g.indent[1:]
-	}
-}
-
-// Generate the output for all the files we're generating output for.
-func (g *Generator) GenerateAllFiles() {
-	for i, file := range g.genFiles {
-		g.Reset()
-		g.Generate(file)
-		g.response.File[i] = plugin.NewCodeGeneratorResponse_File()
-		g.response.File[i].Name = proto.String(GoName(*file.Name))
-		g.response.File[i].Content = proto.String(g.String())
-	}
-}
-
-// Return the FileDescriptor for this FileDescriptorProto
-func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
-	for _, file := range g.allFiles {
-		if file.FileDescriptorProto == fd {
-			return file
-		}
-	}
-	g.fail("could not find file in table:", proto.GetString(fd.Name))
-	return nil
-}
-
-// Fill the response protocol buffer with the generated output for all the files we're
-// supposed to generate.
-func (g *Generator) Generate(file *FileDescriptor) {
-	g.file = g.FileOf(file.FileDescriptorProto)
-	g.GenerateHeader()
-	g.GenerateImports()
-	for _, enum := range g.file.enum {
-		g.GenerateEnum(enum)
-	}
-	for _, desc := range g.file.desc {
-		g.GenerateMessage(desc)
-	}
-	for _, ext := range g.file.ext {
-		g.GenerateExtension(ext)
-	}
-	g.GenerateInitFunction()
-}
-
-// Generate the header, including package definition and imports
-func (g *Generator) GenerateHeader() {
-	g.p("// Code generated by protoc-gen-go from ", Quote(*g.file.Name))
-	g.p("// DO NOT EDIT!")
-	g.p()
-	g.p("package ", g.file.packageName())
-	g.p()
-}
-
-// Generate the header, including package definition and imports
-func (g *Generator) GenerateImports() {
-	if g.file.needProtoImport() {
-		g.p(`import "goprotobuf.googlecode.com/hg/proto"`)
-	}
-	for _, s := range g.file.Dependency {
-		// Need to find the descriptor for this file
-		for _, fd := range g.allFiles {
-			if proto.GetString(fd.Name) == s {
-				filename := GoName(s)
-				if strings.HasSuffix(filename, ".go") {
-					filename = filename[0:len(filename)-3]
-				}
-				g.p("import ", fd.packageName(), " ", Quote(filename))
-				break
-			}
-		}
-	}
-	g.p()
-}
-
-// Generate the enum definitions for this EnumDescriptor.
-func (g *Generator) GenerateEnum(enum *EnumDescriptor) {
-	// The full type name
-	typeName := enum.typeName()
-	// The full type name, CamelCased.
-	ccTypeName := CamelCaseSlice(typeName)
-	ccPrefix := enum.prefix()
-	g.p("type ", ccTypeName, " int32")
-	g.p("const (")
-	g.in()
-	for _, e := range enum.Value {
-		g.p(ccPrefix+*e.Name, " = ", e.Number)
-	}
-	g.out()
-	g.p(")")
-	g.p("var ", ccTypeName, "_name = map[int32] string {")
-	g.in()
-	generated := make(map[int32] bool)	// avoid duplicate values
-	for _, e := range enum.Value {
-		duplicate := ""
-		if _, present := generated[*e.Number]; present {
-			duplicate = "// Duplicate value: "
-		}
-		g.p(duplicate, e.Number, ": ", Quote(*e.Name), ",")
-		generated[*e.Number] = true
-	}
-	g.out()
-	g.p("}")
-	g.p("var ", ccTypeName, "_value = map[string] int32 {")
-	g.in()
-	for _, e := range enum.Value {
-		g.p(Quote(*e.Name), ": ", e.Number, ",")
-	}
-	g.out()
-	g.p("}")
-	g.p("func New", ccTypeName, "(x int32) *", ccTypeName, " {")
-	g.in()
-	g.p("e := ", ccTypeName, "(x)")
-	g.p("return &e")
-	g.out()
-	g.p("}")
-	g.p()
-}
-
-// The tag is a string like "PB(varint,2,opt,name=fieldname,def=7)" that
-// identifies details of the field for the protocol buffer marshaling and unmarshaling
-// code.  The fields are:
-//	wire encoding
-//	protocol tag number
-//	opt,req,rep for optional, required, or repeated
-//	name= the original declared name
-//	enum= the name of the enum type if it is an enum-typed field.
-//	def= string representation of the default value, if any.
-// The default value must be in a representation that can be used at run-time
-// to generate the default value. Thus bools become 0 and 1, for instance.
-func (g *Generator) GoTag(field *descriptor.FieldDescriptorProto, wiretype string) string {
-	optrepreq := ""
-	switch {
-	case IsOptional(field):
-		optrepreq = "opt"
-	case IsRequired(field):
-		optrepreq = "req"
-	case IsRepeated(field):
-		optrepreq = "rep"
-	}
-	defaultValue := proto.GetString(field.DefaultValue)
-	if defaultValue != "" {
-		switch *field.Type {
-		case descriptor.FieldDescriptorProto_TYPE_BOOL:
-			if defaultValue == "true" {
-				defaultValue = "1"
-			} else {
-				defaultValue = "0"
-			}
-		case descriptor.FieldDescriptorProto_TYPE_STRING,
-			descriptor.FieldDescriptorProto_TYPE_BYTES:
-			// Protect frogs.
-			defaultValue = Quote(defaultValue)
-			// Don't need the quotes
-			defaultValue = defaultValue[1 : len(defaultValue)-1]
-		case descriptor.FieldDescriptorProto_TYPE_ENUM:
-			// For enums we need to provide the integer constant.
-			obj := g.objectNamed(proto.GetString(field.TypeName))
-			enum, ok := obj.(*EnumDescriptor)
-			if !ok {
-				g.fail("enum type inconsistent for", CamelCaseSlice(obj.typeName()))
-			}
-			defaultValue = enum.integerValueAsString(defaultValue)
-		}
-		defaultValue = ",def=" + defaultValue
-	}
-	enum := ""
-	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
-		obj := g.objectNamed(proto.GetString(field.TypeName))
-		enum = ",enum=" + obj.packageName() + "." + CamelCaseSlice(obj.typeName())
-	}
-	name := proto.GetString(field.Name)
-	if name == CamelCase(name) {
-		name = ""
-	} else {
-		name = ",name=" + name
-	}
-	return Quote(fmt.Sprintf("PB(%s,%d,%s%s%s%s)",
-		wiretype,
-		proto.GetInt32(field.Number),
-		optrepreq,
-		name,
-		enum,
-		defaultValue))
-}
-
-func NeedsStar(typ descriptor.FieldDescriptorProto_Type) bool {
-	switch typ {
-	case descriptor.FieldDescriptorProto_TYPE_GROUP:
-		return false
-	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
-		return false
-	case descriptor.FieldDescriptorProto_TYPE_BYTES:
-		return false
-	}
-	return true
-}
-
-// The type name appropriate for an item. If it's in the current file,
-// drop the package name and underscore the rest.
-// Otherwise it's from another package; use the underscored package name
-// followed by the field name.  The result has an initial capital.
-func (g *Generator) TypeName(obj Object) string {
-	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.typeName())
-}
-
-// Like TypeName, but always includes the package name even if it's our own package.
-func (g *Generator) TypeNameWithPackage(obj Object) string {
-	return obj.packageName() + CamelCaseSlice(obj.typeName())
-}
-
-// Returns a string representing the type name, and the wire type
-func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
-	// TODO: Options.
-	switch *field.Type {
-	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
-		typ, wire = "float64", "fixed64"
-	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
-		typ, wire = "float32", "fixed32"
-	case descriptor.FieldDescriptorProto_TYPE_INT64:
-		typ, wire = "int64", "varint"
-	case descriptor.FieldDescriptorProto_TYPE_UINT64:
-		typ, wire = "uint64", "varint"
-	case descriptor.FieldDescriptorProto_TYPE_INT32:
-		typ, wire = "int32", "varint"
-	case descriptor.FieldDescriptorProto_TYPE_UINT32:
-		typ, wire = "uint32", "varint"
-	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
-		typ, wire = "uint64", "fixed64"
-	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
-		typ, wire = "uint32", "fixed32"
-	case descriptor.FieldDescriptorProto_TYPE_BOOL:
-		typ, wire = "bool", "varint"
-	case descriptor.FieldDescriptorProto_TYPE_STRING:
-		typ, wire = "string", "bytes"
-	case descriptor.FieldDescriptorProto_TYPE_GROUP:
-		desc := g.objectNamed(proto.GetString(field.TypeName))
-		typ, wire = "*"+g.TypeName(desc), "group"
-	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
-		desc := g.objectNamed(proto.GetString(field.TypeName))
-		typ, wire = "*"+g.TypeName(desc), "bytes"
-	case descriptor.FieldDescriptorProto_TYPE_BYTES:
-		typ, wire = "[]byte", "bytes"
-	case descriptor.FieldDescriptorProto_TYPE_ENUM:
-		desc := g.objectNamed(proto.GetString(field.TypeName))
-		typ, wire = g.TypeName(desc), "varint"
-	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
-		typ, wire = "int32", "fixed32"
-	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
-		typ, wire = "int64", "fixed64"
-	case descriptor.FieldDescriptorProto_TYPE_SINT32:
-		typ, wire = "int32", "zigzag32"
-	case descriptor.FieldDescriptorProto_TYPE_SINT64:
-		typ, wire = "int64", "zigzag64"
-	default:
-		g.fail("unknown type for", proto.GetString(field.Name))
-	}
-	if IsRepeated(field) {
-		typ = "[]" + typ
-	} else if NeedsStar(*field.Type) {
-		typ = "*" + typ
-	}
-	return
-}
-
-// Generate the type and default constant definitions for this Descriptor.
-func (g *Generator) GenerateMessage(message *Descriptor) {
-	// The full type name
-	typeName := message.typeName()
-	// The full type name, CamelCased.
-	ccTypeName := CamelCaseSlice(typeName)
-
-	g.p("type ", ccTypeName, " struct {")
-	g.in()
-	for _, field := range message.Field {
-		fieldname := CamelCase(*field.Name)
-		typename, wiretype := g.GoType(message, field)
-		tag := g.GoTag(field, wiretype)
-		g.p(fieldname, "\t", typename, "\t", tag)
-	}
-	if len(message.ExtensionRange) > 0 {
-		g.p("XXX_extensions\t\tmap[int32][]byte")
-	}
-	g.p("XXX_unrecognized\t[]byte")
-	g.out()
-	g.p("}")
-
-	// Reset and New functions
-	g.p("func (this *", ccTypeName, ") Reset() {")
-	g.in()
-	g.p("*this = ", ccTypeName, "{}")
-	g.out()
-	g.p("}")
-	g.p("func New", ccTypeName, "() *", ccTypeName, " {")
-	g.in()
-	g.p("return new(", ccTypeName, ")")
-	g.out()
-	g.p("}")
-
-	// Extension support methods
-	if len(message.ExtensionRange) > 0 {
-		g.p()
-		g.p("var extRange_", ccTypeName, " = []proto.ExtensionRange{")
-		g.in()
-		for _, r := range message.ExtensionRange {
-			end := fmt.Sprint(*r.End - 1)  // make range inclusive on both ends
-			g.p("proto.ExtensionRange{", r.Start, ", ", end, "},")
-		}
-		g.out()
-		g.p("}")
-		g.p("func (*", ccTypeName, ") ExtensionRangeArray() []proto.ExtensionRange {")
-		g.in()
-		g.p("return extRange_", ccTypeName)
-		g.out()
-		g.p("}")
-		g.p("func (this *", ccTypeName, ") ExtensionMap() map[int32][]byte {")
-		g.in()
-		g.p("if this.XXX_extensions == nil {")
-		g.in()
-		g.p("this.XXX_extensions = make(map[int32][]byte)")
-		g.out()
-		g.p("}")
-		g.p("return this.XXX_extensions")
-		g.out()
-		g.p("}")
-	}
-
-	// Default constants
-	for _, field := range message.Field {
-		def := proto.GetString(field.DefaultValue)
-		if def == "" {
-			continue
-		}
-		fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
-		typename, _ := g.GoType(message, field)
-		if typename[0] == '*' {
-			typename = typename[1:]
-		}
-		kind := "const "
-		switch {
-		case typename == "bool":
-		case typename == "string":
-			def = Quote(def)
-		case typename == "[]byte":
-			def = "[]byte(" + Quote(def) + ")"
-			kind = "var "
-		case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
-			// Must be an enum.  Need to construct the prefixed name.
-			obj := g.objectNamed(proto.GetString(field.TypeName))
-			enum, ok := obj.(*EnumDescriptor)
-			if !ok {
-				log.Stderr("don't know how to generate constant for", fieldname)
-				continue
-			}
-			def = enum.prefix() + def
-		}
-		g.p(kind, fieldname, " ", typename, " = ", def)
-	}
-	g.p()
-
-	for _, ext := range message.ext {
-		g.GenerateExtension(ext)
-	}
-}
-
-// Generate the extension descriptor for this ExtensionDescriptor.
-func (g *Generator) GenerateExtension(ext *ExtensionDescriptor) {
-	// The full type name
-	typeName := ext.typeName()
-	// Each scope of the extension is individually CamelCased, and all are joined with "_" with a "E_" prefix.
-	for i, s := range typeName {
-		typeName[i] = CamelCase(s)
-	}
-	ccTypeName := "E_" + strings.Join(typeName, "_")
-
-	extendedType := "*" + g.TypeName(g.objectNamed(*ext.Extendee))
-	field := ext.FieldDescriptorProto
-	fieldType, wireType := g.GoType(ext.parent, field)
-	tag := g.GoTag(field, wireType)
-
-	g.p("var ", ccTypeName, " = &proto.ExtensionDesc{")
-	g.in()
-	g.p("ExtendedType: (", extendedType, ")(nil),")
-	g.p("ExtensionType: (", fieldType, ")(nil),")
-	g.p("Field: ", field.Number, ",")
-	g.p("Tag: ", tag, ",")
-
-	g.out()
-	g.p("}")
-	g.p()
-}
-
-func (g *Generator) GenerateInitFunction() {
-	g.p("func init() {")
-	g.in()
-	for _, enum := range g.file.enum {
-		g.GenerateEnumRegistration(enum)
-	}
-	g.out()
-	g.p("}")
-}
-
-func (g *Generator) GenerateEnumRegistration(enum *EnumDescriptor) {
-	pkg := g.packageName + "." // We always print the full package name here.
-	// The full type name
-	typeName := enum.typeName()
-	// The full type name, CamelCased.
-	ccTypeName := CamelCaseSlice(typeName)
-	g.p("proto.RegisterEnum(", Quote(pkg+ccTypeName), ", ", ccTypeName+"_name, ", ccTypeName+"_value)")
-}
-
-// And now lots of helper functions.
-
-// Return change foo_bar_Baz to FooBar_Baz.
-func CamelCase(name string) string {
-	elems := strings.Split(name, "_", 0)
-	for i, e := range elems {
-		if e == "" {
-			elems[i] = "_"
-			continue
-		}
-		runes := []int(e)
-		if unicode.IsLower(runes[0]) {
-			runes[0] = unicode.ToUpper(runes[0])
-			elems[i] = string(runes)
-		} else {
-			if i > 0 {
-				elems[i] = "_" + e
-			}
-		}
-	}
-	s := strings.Join(elems, "")
-	// Name must not begin with an underscore.
-	if len(s) > 0 && s[0] == '_' {
-		s = "X" + s[1:]
-	}
-	return s
-}
-
-// Like CamelCase, but the argument is a slice of strings to
-// be concatenated with "_"
-func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
-
-// Turn a sliced name into a dotted name
-func DottedSlice(elem []string) string { return strings.Join(elem, ".") }
-
-// Return a Go-source quoted string representation of s.
-func Quote(s string) string { return fmt.Sprintf("%q", s) }
-
-// Given a .proto file name, return the output name for the generated Go program.
-func GoName(name string) string {
-	if strings.HasSuffix(name, ".proto") {
-		name = name[0 : len(name)-6]
-	}
-	return name + ".pb.go"
-}
-
-// Is this field optional?
-func IsOptional(field *descriptor.FieldDescriptorProto) bool {
-	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
-}
-
-// Is this field required?
-func IsRequired(field *descriptor.FieldDescriptorProto) bool {
-	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
-}
-
-// Is this field repeated?
-func IsRepeated(field *descriptor.FieldDescriptorProto) bool {
-	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
-}
-
-// Mapping function used to generate Go names from package names, which can be dotted.
-func DotToUnderscore(rune int) int {
-	if rune == '.' {
-		return '_'
-	}
-	return rune
-}
