Add compressed file descriptor code generation.

This is fairly undocumented for now, but should be sufficiently
obvious for those wanting such an advanced feature anyway.
The only non-obvious part is that the []int returned by
Descriptor/EnumDescriptor describes the sequence of indexes used
to navigate from the FileDescriptorProto to the relevant
DescriptorProto/EnumDescriptorProto.
diff --git a/protoc-gen-go/generator/generator.go b/protoc-gen-go/generator/generator.go
index 9d987fa..1ff06b8 100644
--- a/protoc-gen-go/generator/generator.go
+++ b/protoc-gen-go/generator/generator.go
@@ -39,6 +39,7 @@
 import (
 	"bufio"
 	"bytes"
+	"compress/gzip"
 	"fmt"
 	"go/parser"
 	"go/printer"
@@ -1133,6 +1134,8 @@
 	// Run the plugins before the imports so we know which imports are necessary.
 	g.runPlugins(file)
 
+	g.generateFileDescriptor(file)
+
 	// Generate header and imports last, though they appear first in the output.
 	rem := g.Buffer
 	g.Buffer = new(bytes.Buffer)
@@ -1393,6 +1396,14 @@
 		g.P("}")
 	}
 
+	var indexes []string
+	for m := enum.parent; m != nil; m = m.parent {
+		// XXX: skip groups?
+		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
+	}
+	indexes = append(indexes, strconv.Itoa(enum.index))
+	g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) { return fileDescriptor", g.file.index, ", []int{", strings.Join(indexes, ", "), "} }")
+
 	g.P()
 }
 
@@ -1793,6 +1804,14 @@
 	g.P("func (m *", ccTypeName, ") Reset() { *m = ", ccTypeName, "{} }")
 	g.P("func (m *", ccTypeName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
 	g.P("func (*", ccTypeName, ") ProtoMessage() {}")
+	if !message.group {
+		var indexes []string
+		for m := message; m != nil; m = m.parent {
+			// XXX: skip groups?
+			indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
+		}
+		g.P("func (*", ccTypeName, ") Descriptor() ([]byte, []int) { return fileDescriptor", g.file.index, ", []int{", strings.Join(indexes, ", "), "} }")
+	}
 
 	// Extension support methods
 	var hasExtensions, isMessageSet bool
@@ -2396,6 +2415,44 @@
 	g.init = nil
 }
 
+func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
+	// Make a copy and trim source_code_info data.
+	// TODO: Trim this more when we know exactly what we need.
+	pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
+	pb.SourceCodeInfo = nil
+
+	b, err := proto.Marshal(pb)
+	if err != nil {
+		g.Fail(err.Error())
+	}
+
+	var buf bytes.Buffer
+	w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
+	w.Write(b)
+	w.Close()
+	b = buf.Bytes()
+
+	g.P("var fileDescriptor", file.index, " = []byte{")
+	g.In()
+	g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
+	for len(b) > 0 {
+		n := 16
+		if n > len(b) {
+			n = len(b)
+		}
+
+		s := ""
+		for _, c := range b[:n] {
+			s += fmt.Sprintf("0x%02x,", c)
+		}
+		g.P(s)
+
+		b = b[n:]
+	}
+	g.Out()
+	g.P("}")
+}
+
 func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
 	// // We always print the full (proto-world) package name here.
 	pkg := enum.File().GetPackage()
diff --git a/protoc-gen-go/testdata/Makefile b/protoc-gen-go/testdata/Makefile
index eceea71..a85cc56 100644
--- a/protoc-gen-go/testdata/Makefile
+++ b/protoc-gen-go/testdata/Makefile
@@ -45,6 +45,9 @@
 
 golden:
 	make -B my_test/test.pb.go
+	sed -i '/return.*fileDescriptor/d' my_test/test.pb.go
+	sed -i '/^var fileDescriptor/,/^}/d' my_test/test.pb.go
+	gofmt -w my_test/test.pb.go
 	diff -w my_test/test.pb.go my_test/test.pb.go.golden
 
 nuke:	clean