encoding/protobuf: add Builder API

A Builder parses a collection of .proto file and
organizes them according to a CUE package
layout. The exising Parse function is expressed
in this new API.

Issue #5

Change-Id: I980e7654d2b666dd1c637ad6d80f513096907a0b
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/2364
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
diff --git a/encoding/protobuf/parse.go b/encoding/protobuf/parse.go
index 0753199..ad49a04 100644
--- a/encoding/protobuf/parse.go
+++ b/encoding/protobuf/parse.go
@@ -24,21 +24,31 @@
 	"strconv"
 	"strings"
 	"text/scanner"
+	"unicode"
 
 	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/errors"
 	"cuelang.org/go/cue/parser"
 	"cuelang.org/go/cue/token"
 	"cuelang.org/go/internal/source"
 	"github.com/emicklei/proto"
-	"golang.org/x/xerrors"
 )
 
-type sharedState struct {
-	paths []string
-}
+func (s *Builder) parse(filename string, src interface{}) (p *protoConverter, err error) {
+	if filename == "" {
+		return nil, errors.Newf(token.NoPos, "empty filename")
+	}
+	if r, ok := s.fileCache[filename]; ok {
+		return r.p, r.err
+	}
+	defer func() {
+		s.fileCache[filename] = result{p, err}
+	}()
 
-func (s *sharedState) parse(filename string, src interface{}) (p *protoConverter, err error) {
 	b, err := source.Read(filename, src)
+	if err != nil {
+		return nil, err
+	}
 
 	parser := proto.NewParser(bytes.NewReader(b))
 	if filename != "" {
@@ -46,14 +56,19 @@
 	}
 	d, err := parser.Parse()
 	if err != nil {
-		return nil, xerrors.Errorf("protobuf: %w", err)
+		return nil, errors.Newf(token.NoPos, "protobuf: %v", err)
 	}
 
+	tfile := token.NewFile(filename, 0, len(b))
+	tfile.SetLinesForContent(b)
+
 	p = &protoConverter{
+		id:      filename,
 		state:   s,
-		tfile:   token.NewFile(filename, 0, len(b)),
+		tfile:   tfile,
 		used:    map[string]bool{},
 		symbols: map[string]bool{},
+		aliases: map[string]string{},
 	}
 
 	defer func() {
@@ -105,7 +120,9 @@
 	for _, e := range d.Elements {
 		switch x := e.(type) {
 		case *proto.Import:
-			p.doImport(x)
+			if err := p.doImport(x); err != nil {
+				return nil, err
+			}
 		}
 	}
 
@@ -121,11 +138,14 @@
 		used = append(used, k)
 	}
 	sort.Strings(used)
+	p.sorted = used
 
 	for _, v := range used {
-		imports.Specs = append(imports.Specs, &ast.ImportSpec{
+		spec := &ast.ImportSpec{
 			Path: &ast.BasicLit{Kind: token.STRING, Value: strconv.Quote(v)},
-		})
+		}
+		imports.Specs = append(imports.Specs, spec)
+		p.file.Imports = append(p.file.Imports, spec)
 	}
 
 	if len(imports.Specs) == 0 {
@@ -138,11 +158,12 @@
 // A protoConverter converts a proto definition to CUE. Proto files map to
 // CUE files one to one.
 type protoConverter struct {
-	state *sharedState
+	state *Builder
 	tfile *token.File
 
 	proto3 bool
 
+	id        string
 	protoPkg  string
 	goPkg     string
 	goPkgPath string
@@ -151,23 +172,26 @@
 	file   *ast.File
 	inBody bool
 
-	imports map[string]string
-	used    map[string]bool
+	sorted []string
+	used   map[string]bool
 
 	path    []string
 	scope   []map[string]mapping // for symbols resolution within package.
 	symbols map[string]bool      // symbols provided by package
+	aliases map[string]string    // for shadowed packages
 }
 
 type mapping struct {
-	ref string
-	pkg *protoConverter
+	ref   string
+	alias string // alias for the type, if exists.
+	pkg   *protoConverter
 }
 
 type pkgInfo struct {
 	importPath string // the import path
 	goPath     string // The Go import path
 	shortName  string // Used for the cue package path, default is base of goPath
+	protoName  string // the protobuf package name
 }
 
 func (p *protoConverter) toCUEPos(pos scanner.Position) token.Pos {
@@ -210,13 +234,52 @@
 	p.scope = p.scope[:len(p.scope)-1]
 }
 
+func (p *protoConverter) uniqueTop(name string) string {
+	if len(p.path) == 0 {
+		return name
+	}
+	a := strings.SplitN(name, ".", 2)
+	if p.path[len(p.path)-1] == a[0] {
+		first := a[0]
+		alias, ok := p.aliases[first]
+		if !ok {
+			// TODO: this is likely to be okay, but find something better.
+			alias = "__" + first
+			p.file.Decls = append(p.file.Decls, &ast.Alias{
+				Ident: ast.NewIdent(alias),
+				Expr:  ast.NewIdent(first),
+			})
+			p.aliases[first] = alias
+		}
+		if len(a) > 1 {
+			alias += "." + a[1]
+		}
+		return alias
+	}
+	return name
+}
+
+func (p *protoConverter) toExpr(pos scanner.Position, name string) (expr ast.Expr) {
+	a := strings.Split(name, ".")
+	for i, s := range a {
+		if i == 0 {
+			expr = &ast.Ident{NamePos: p.toCUEPos(pos), Name: s}
+			continue
+		}
+		expr = &ast.SelectorExpr{X: expr, Sel: ast.NewIdent(s)}
+	}
+	return expr
+}
+
 func (p *protoConverter) resolve(pos scanner.Position, name string, options []*proto.Option) string {
 	if strings.HasPrefix(name, ".") {
 		return p.resolveTopScope(pos, name[1:], options)
 	}
 	for i := len(p.scope) - 1; i > 0; i-- {
 		if m, ok := p.scope[i][name]; ok {
-			return m.ref
+			cueName := m.ref
+			cueName = strings.Replace(m.ref, ".", "_", -1)
+			return cueName
 		}
 	}
 	return p.resolveTopScope(pos, name, options)
@@ -232,8 +295,10 @@
 		if m, ok := p.scope[0][name[:i]]; ok {
 			if m.pkg != nil {
 				p.used[m.pkg.goPkgPath] = true
+				// TODO: do something more principled.
 			}
-			return m.ref + name[i:]
+			cueName := strings.Replace(name[i:], ".", "_", -1)
+			return p.uniqueTop(m.ref + cueName)
 		}
 	}
 	if s, ok := protoToCUE(name, options); ok {
@@ -243,9 +308,9 @@
 	return ""
 }
 
-func (p *protoConverter) doImport(v *proto.Import) {
+func (p *protoConverter) doImport(v *proto.Import) error {
 	if v.Filename == "cue/cue.proto" {
-		return
+		return nil
 	}
 
 	filename := ""
@@ -259,6 +324,12 @@
 		break
 	}
 
+	if filename == "" {
+		err := errors.Newf(p.toCUEPos(v.Position), "could not find import %q", v.Filename)
+		p.state.addErr(err)
+		return err
+	}
+
 	p.mapBuiltinPackage(v.Position, v.Filename, filename == "")
 
 	imp, err := p.state.parse(filename, nil)
@@ -284,7 +355,7 @@
 				if imp.goPkgPath == p.goPkgPath {
 					pkg = nil
 				}
-				p.scope[0][ref] = mapping{prefix + k, pkg}
+				p.scope[0][ref] = mapping{prefix + k, "", pkg}
 			}
 		}
 		if len(pkgNamespace) == 0 {
@@ -296,6 +367,7 @@
 		pkgNamespace = pkgNamespace[1:]
 		curNamespace = curNamespace[1:]
 	}
+	return nil
 }
 
 func (p *protoConverter) stringLit(pos scanner.Position, s string) *ast.BasicLit {
@@ -353,7 +425,10 @@
 	case *proto.Import:
 		// already handled.
 
-	case *proto.Extensions:
+	case *proto.Service:
+		// TODO: handle services.
+
+	case *proto.Extensions, *proto.Reserved:
 		// no need to handle
 
 	default:
@@ -362,6 +437,11 @@
 }
 
 func (p *protoConverter) message(v *proto.Message) {
+	if v.IsExtend {
+		// TODO: we are not handling extensions as for now.
+		return
+	}
+
 	defer func(saved []string) { p.path = saved }(p.path)
 	p.path = append(p.path, v.Name)
 
@@ -383,7 +463,6 @@
 	f := &ast.Field{Label: ref, Value: s}
 	addComments(f, 1, v.Comment, nil)
 
-	// In CUE a message is always defined at the top level.
 	p.file.Decls = append(p.file.Decls, f)
 
 	for i, e := range v.Elements {
@@ -408,12 +487,15 @@
 		}
 
 	case *proto.MapField:
+		defer func(saved []string) { p.path = saved }(p.path)
+		p.path = append(p.path, x.Name)
+
 		f := &ast.Field{}
 
 		// All keys are converted to strings.
 		// TODO: support integer keys.
 		f.Label = &ast.TemplateLabel{Ident: ast.NewIdent("_")}
-		f.Value = ast.NewIdent(p.resolve(x.Position, x.Type, x.Options))
+		f.Value = p.toExpr(x.Position, p.resolve(x.Position, x.Type, x.Options))
 
 		name := p.ident(x.Position, x.Name)
 		f = &ast.Field{
@@ -440,11 +522,11 @@
 	case *proto.Oneof:
 		p.oneOf(x)
 
-	case *proto.Extensions:
+	case *proto.Extensions, *proto.Reserved:
 		// no need to handle
 
 	default:
-		failf(scanner.Position{}, "unsupported type %T", v)
+		failf(scanner.Position{}, "unsupported field type %T", v)
 	}
 }
 
@@ -467,12 +549,16 @@
 // Enums are always defined at the top level. The name of a nested enum
 // will be prefixed with the name of its parent and an underscore.
 func (p *protoConverter) enum(x *proto.Enum) {
+
 	if len(x.Elements) == 0 {
 		failf(x.Position, "empty enum")
 	}
 
 	name := p.subref(x.Position, x.Name)
 
+	defer func(saved []string) { p.path = saved }(p.path)
+	p.path = append(p.path, x.Name)
+
 	p.addNames(x.Elements)
 
 	if len(p.path) == 0 {
@@ -491,6 +577,9 @@
 	d := &ast.Field{Label: valueName, Value: valueMap}
 	// addComments(valueMap, 1, x.Comment, nil)
 
+	if strings.Contains(name.Name, "google") {
+		panic(name.Name)
+	}
 	p.file.Decls = append(p.file.Decls, enum, d)
 
 	// The line comments for an enum field need to attach after the '|', which
@@ -570,13 +659,16 @@
 }
 
 func (p *protoConverter) parseField(s *ast.StructLit, i int, x *proto.Field) *ast.Field {
+	defer func(saved []string) { p.path = saved }(p.path)
+	p.path = append(p.path, x.Name)
+
 	f := &ast.Field{}
 	addComments(f, i, x.Comment, x.InlineComment)
 
 	name := p.ident(x.Position, x.Name)
 	f.Label = name
 	typ := p.resolve(x.Position, x.Type, x.Options)
-	f.Value = ast.NewIdent(typ)
+	f.Value = p.toExpr(x.Position, typ)
 	s.Elts = append(s.Elts, f)
 
 	o := optionParser{message: s, field: f}
@@ -635,7 +727,34 @@
 
 			// TODO: should CUE support nested attributes?
 			source := o.Constant.SourceRepresentation()
-			p.tags += "," + quote("option("+o.Name+","+source+")")
+			p.tags += ","
+			switch source {
+			case "true":
+				p.tags += quoteOption(o.Name)
+			default:
+				p.tags += quoteOption(o.Name + "=" + source)
+			}
 		}
 	}
 }
+
+func quoteOption(s string) string {
+	needQuote := false
+	for _, r := range s {
+		if !unicode.In(r, unicode.L, unicode.N) {
+			needQuote = true
+			break
+		}
+	}
+	if !needQuote {
+		return s
+	}
+	if !strings.ContainsAny(s, `"\`) {
+		return strconv.Quote(s)
+	}
+	esc := `\#`
+	for strings.Contains(s, esc) {
+		esc += "#"
+	}
+	return esc[1:] + `"` + s + `"` + esc[1:]
+}
diff --git a/encoding/protobuf/protobuf.go b/encoding/protobuf/protobuf.go
index 5b11e4d..c433022 100644
--- a/encoding/protobuf/protobuf.go
+++ b/encoding/protobuf/protobuf.go
@@ -15,17 +15,280 @@
 // Package protobuf defines functionality for parsing protocol buffer
 // definitions and instances.
 //
+// Protobuf definitions can be annotated with CUE constraints that are
+// included in the generated CUE:
+//    (cue.val)     string        CUE expression defining a constraint for this
+//                                field. The string may refer to other fields
+//                                in a message definition using their JSON name.
+//
+//    (cue.opt)     FieldOptions
+//       required   bool          Defines the field is required. Use with
+//                                caution.
+//
 package protobuf
 
 import (
+	"os"
+	"path/filepath"
+	"sort"
+	"strings"
+
 	"cuelang.org/go/cue/ast"
+	"cuelang.org/go/cue/build"
+	"cuelang.org/go/cue/errors"
+	"cuelang.org/go/cue/format"
+	"cuelang.org/go/cue/parser"
+	"cuelang.org/go/cue/token"
+	"github.com/mpvl/unique"
 )
 
 // Config specifies the environment into which to parse a proto definition file.
 type Config struct {
+	// Root specifies the root of the CUE project, which typically coincides
+	// with, for example, a version control repository root or the Go module.
+	// Any imports of proto files within the directory tree of this of this root
+	// are considered to be "project files" and are generated at the
+	// corresponding location with this hierarchy. Any other imports are
+	// considered to be external. Files for such imports are rooted under the
+	// $Root/pkg/, using the Go package path specified in the .proto file.
+	Root string
+
+	// Module is the Go package import path of the module root. It is the value
+	// as after "module" in a go.mod file, if a module file is present.
+	Module string // TODO: determine automatically if unspecified.
+
+	// Paths defines the include directory in which to search for imports.
 	Paths []string
 }
 
+// A Builder converts a collection of proto files, typically belonging to one
+// repo or module, to CUE. It thereby observes the CUE package layout.
+//
+// CUE observes the same package layout as Go and requires .proto files to have
+// the go_package directive. Generated CUE files are put in the same directory
+// as their corresponding .proto files if the .proto files are located in the
+// specified Root (or current working directory if none is specified).
+// All other imported files are assigned to the CUE pkg dir ($Root/pkg)
+// according to their Go package import path.
+//
+type Builder struct {
+	root   string
+	cwd    string
+	module string
+	paths  []string
+
+	fileCache map[string]result
+	instCache map[string]*build.Instance
+	imports   map[string]*build.Instance
+
+	errs errors.List
+	done bool
+}
+
+type result struct {
+	p   *protoConverter
+	err error
+}
+
+// NewBuilder creates a Builder. If the configuration contained any errors it
+// will be observable by the Err method fo the Builder. It is safe, however, to
+// only check errors after building the output.
+func NewBuilder(c *Config) *Builder {
+	cwd, _ := os.Getwd()
+	b := &Builder{
+		root:      c.Root,
+		cwd:       cwd,
+		paths:     c.Paths,
+		module:    c.Module,
+		fileCache: map[string]result{},
+		imports:   map[string]*build.Instance{},
+	}
+
+	if b.root == "" {
+		b.root = b.cwd
+	}
+
+	return b
+}
+
+// Err returns the errors accumulated during testing. The returned error may be
+// of type cuelang.org/go/cue/errors.List.
+func (b *Builder) Err() error {
+	return b.errs.Err()
+}
+
+func (b *Builder) addErr(err error) {
+	switch err := err.(type) {
+	case errors.Error:
+		b.errs.Add(err)
+	default:
+		b.errs.AddNewf(token.NoPos, "unknown error: %v", err)
+	}
+}
+
+// AddFile adds a proto definition file to be converted into CUE by the builder.
+// Relatives paths are always taken relative to the Root with which the b is
+// configured.
+//
+// AddFile assumes that the proto file compiles with protoc and may not report
+// an error if it does not. Imports are resolved using the paths defined in
+// Config.
+//
+func (b *Builder) AddFile(filename string, src interface{}) error {
+	if b.done {
+		b.errs.Add(errors.Newf(token.NoPos, "protobuf: cannot call AddFile: Instances was already called"))
+		return b.Err()
+	}
+	if b.root != b.cwd && !filepath.IsAbs(filename) {
+		filename = filepath.Join(b.root, filename)
+	}
+	_, err := b.parse(filename, src)
+	return err
+}
+
+// TODO: some way of (recursively) adding multiple proto files with filter.
+
+// Files returns a File for each proto file that was added or imported,
+// recursively.
+func (b *Builder) Files() (files []*ast.File, err error) {
+	defer func() { err = b.Err() }()
+	b.done = true
+
+	instances, err := b.Instances()
+	if err != nil {
+		return nil, err
+	}
+
+	for _, p := range instances {
+		for _, f := range p.Files {
+			files = append(files, f)
+		}
+	}
+	return files, nil
+}
+
+// Instances creates a build.Instances for every package for which a proto file
+// was added to the builder. This includes transitive dependencies. It does not
+// write the generated files to disk.
+//
+// The returned instances can be passed to cue.Build to generated the
+// corresponding CUE instances.
+//
+// All import paths are located within the specified Root, where external
+// packages are located under $Root/pkg. Instances for builtin (like time)
+// packages may be omitted, and if not will have no associated files.
+func (b *Builder) Instances() (instances []*build.Instance, err error) {
+	defer func() { err = b.Err() }()
+	b.done = true
+
+	for _, r := range b.fileCache {
+		if r.err != nil {
+			b.addErr(r.err)
+			continue
+		}
+		inst := b.getInst(r.p)
+		if inst == nil {
+			continue
+		}
+
+		// Set canonical CUE path for generated file.
+		f := r.p.file
+		base := filepath.Base(f.Filename)
+		base = base[:len(base)-len(".proto")] + "_proto_gen.cue"
+		f.Filename = filepath.Join(inst.Dir, base)
+		buf, err := format.Node(f)
+		if err != nil {
+			b.addErr(err)
+			// return nil, err
+			continue
+		}
+		f, err = parser.ParseFile(f.Filename, buf, parser.ParseComments)
+		if err != nil {
+			panic(err)
+			b.addErr(err)
+			// return nil, err
+			continue
+		}
+
+		inst.Files = append(inst.Files, f)
+		// inst.CUEFiles = append(inst.CUEFiles, f.Filename)
+		// err := parser.Resolve(f)
+		// if err != nil {
+		// 	return nil, err
+		// }
+
+		for pkg := range r.p.used {
+			inst.ImportPaths = append(inst.ImportPaths, pkg)
+		}
+	}
+
+	for _, p := range b.imports {
+		instances = append(instances, p)
+		sort.Strings(p.ImportPaths)
+		unique.Strings(&p.ImportPaths)
+		for _, i := range p.ImportPaths {
+			if imp := b.imports[i]; imp != nil {
+				p.Imports = append(p.Imports, imp)
+			}
+		}
+
+		sort.Slice(p.Files, func(i, j int) bool {
+			return p.Files[i].Filename < p.Files[j].Filename
+		})
+	}
+	sort.Slice(instances, func(i, j int) bool {
+		return instances[i].ImportPath < instances[j].ImportPath
+	})
+
+	if err := b.errs.Err(); err != nil {
+		return instances, err
+	}
+	return instances, nil
+}
+
+func (b *Builder) getInst(p *protoConverter) *build.Instance {
+	if b.errs != nil {
+		return nil
+	}
+	importPath := p.goPkgPath
+	if importPath == "" {
+		b.errs.AddNewf(token.NoPos, "no go_package for proto package %q in file %s", p.id, p.file.Filename)
+		// TODO: fine an alternative. Is proto package good enough?
+		return nil
+	}
+
+	dir := b.root
+	path := importPath
+	if !strings.HasPrefix(path, b.module) {
+		dir = filepath.Join(dir, "pkg", path)
+	} else {
+		dir = filepath.Join(dir, path[len(b.module)+1:])
+		want := filepath.Dir(p.file.Filename)
+		if !filepath.IsAbs(want) {
+			want = filepath.Join(b.root, want)
+		}
+		if dir != want {
+			b.errs.AddNewf(token.NoPos,
+				"file %s mapped to inconsistent path %s; module name %q may be inconsistent with root dir %s",
+				want, dir, b.module, b.root,
+			)
+		}
+	}
+
+	inst := b.imports[importPath]
+	if inst == nil {
+		inst = &build.Instance{
+			Root:        b.root,
+			Dir:         dir,
+			ImportPath:  importPath,
+			PkgName:     p.goPkg,
+			DisplayPath: p.protoPkg,
+		}
+		b.imports[importPath] = inst
+	}
+	return inst
+}
+
 // Parse parses a single proto file and returns its contents translated to a CUE
 // file. If src is not nil, it will use this as the contents of the file. It may
 // be a string, []byte or io.Reader. Otherwise Parse will open the given file
@@ -34,24 +297,18 @@
 // Parse assumes the proto file compiles with protoc and may not report an error
 // if it does not. Imports are resolved using the paths defined in Config.
 //
-// The following field options are supported:
-//    (cue.val)     string        CUE constraint for this field. The string may
-//                                refer to other fields in a message definition.
-//    (cue.opt)     FieldOptions
-//       required   bool          Defines the field is required. Use with
-//                                caution.
 func Parse(filename string, src interface{}, c *Config) (f *ast.File, err error) {
 	if c == nil {
 		c = &Config{}
 	}
-	state := &sharedState{
-		paths: c.Paths,
-	}
-	p, err := state.parse(filename, src)
+	b := NewBuilder(c)
+
+	p, err := b.parse(filename, src)
 	if err != nil {
 		return nil, err
 	}
-	return p.file, nil
+	p.file.Filename = filename[:len(filename)-len(".proto")] + "_gen.cue"
+	return p.file, b.Err()
 }
 
 // TODO
diff --git a/encoding/protobuf/protobuf_test.go b/encoding/protobuf/protobuf_test.go
index 9864728..8e4a45b 100644
--- a/encoding/protobuf/protobuf_test.go
+++ b/encoding/protobuf/protobuf_test.go
@@ -19,9 +19,12 @@
 	"flag"
 	"fmt"
 	"io/ioutil"
+	"os"
 	"path/filepath"
+	"strings"
 	"testing"
 
+	"cuelang.org/go/cue/ast"
 	"cuelang.org/go/cue/format"
 	"github.com/kr/pretty"
 )
@@ -36,9 +39,10 @@
 	}
 	for _, file := range testCases {
 		t.Run(file, func(t *testing.T) {
-			filename := filepath.Join("testdata", filepath.FromSlash(file))
+			root := "testdata/istio.io/api"
+			filename := filepath.Join(root, filepath.FromSlash(file))
 			c := &Config{
-				Paths: []string{"testdata"},
+				Paths: []string{"testdata", root},
 			}
 
 			out := &bytes.Buffer{}
@@ -67,3 +71,84 @@
 		})
 	}
 }
+
+func TestBuild(t *testing.T) {
+	cwd, _ := os.Getwd()
+	root := filepath.Join(cwd, "testdata/istio.io/api")
+	c := &Config{
+		Root:   root,
+		Module: "istio.io/api",
+		Paths: []string{
+			root,
+			filepath.Join(cwd, "testdata"),
+		},
+	}
+
+	b := NewBuilder(c)
+	b.AddFile("networking/v1alpha3/gateway.proto", nil)
+	b.AddFile("mixer/v1/attributes.proto", nil)
+	b.AddFile("mixer/v1/mixer.proto", nil)
+	b.AddFile("mixer/v1/config/client/client_config.proto", nil)
+
+	files, err := b.Files()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if *update {
+		for _, f := range files {
+			b, err := format.Node(f)
+			if err != nil {
+				t.Fatal(err)
+			}
+			_ = os.MkdirAll(filepath.Dir(f.Filename), 0755)
+			err = ioutil.WriteFile(f.Filename, b, 0644)
+			if err != nil {
+				t.Fatal(err)
+			}
+		}
+		return
+	}
+
+	gotFiles := map[string]*ast.File{}
+
+	for _, f := range files {
+		rel, err := filepath.Rel(cwd, f.Filename)
+		if err != nil {
+			t.Fatal(err)
+		}
+		gotFiles[rel] = f
+	}
+
+	filepath.Walk("testdata/istio.io/api", func(path string, fi os.FileInfo, err error) error {
+		if err != nil || fi.IsDir() || !strings.HasSuffix(path, ".cue") {
+			return err
+		}
+
+		f := gotFiles[path]
+		if f == nil {
+			t.Errorf("did not produce file %q", path)
+			return nil
+		}
+		delete(gotFiles, path)
+
+		got, err := format.Node(f)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		want, err := ioutil.ReadFile(path)
+		if err != nil {
+			t.Fatal(err)
+		}
+
+		if !bytes.Equal(got, want) {
+			t.Errorf("%s: files differ", path)
+		}
+		return nil
+	})
+
+	for filename := range gotFiles {
+		t.Errorf("did not expect file %q", filename)
+	}
+}
diff --git a/encoding/protobuf/testdata/gogoproto/gogo.proto b/encoding/protobuf/testdata/gogoproto/gogo.proto
new file mode 100644
index 0000000..b80c856
--- /dev/null
+++ b/encoding/protobuf/testdata/gogoproto/gogo.proto
@@ -0,0 +1,144 @@
+// Protocol Buffers for Go with Gadgets
+//
+// Copyright (c) 2013, The GoGo Authors. All rights reserved.
+// http://github.com/gogo/protobuf
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+syntax = "proto2";
+package gogoproto;
+
+import "google/protobuf/descriptor.proto";
+
+option java_package = "com.google.protobuf";
+option java_outer_classname = "GoGoProtos";
+option go_package = "github.com/gogo/protobuf/gogoproto";
+
+extend google.protobuf.EnumOptions {
+	optional bool goproto_enum_prefix = 62001;
+	optional bool goproto_enum_stringer = 62021;
+	optional bool enum_stringer = 62022;
+	optional string enum_customname = 62023;
+	optional bool enumdecl = 62024;
+}
+
+extend google.protobuf.EnumValueOptions {
+	optional string enumvalue_customname = 66001;
+}
+
+extend google.protobuf.FileOptions {
+	optional bool goproto_getters_all = 63001;
+	optional bool goproto_enum_prefix_all = 63002;
+	optional bool goproto_stringer_all = 63003;
+	optional bool verbose_equal_all = 63004;
+	optional bool face_all = 63005;
+	optional bool gostring_all = 63006;
+	optional bool populate_all = 63007;
+	optional bool stringer_all = 63008;
+	optional bool onlyone_all = 63009;
+
+	optional bool equal_all = 63013;
+	optional bool description_all = 63014;
+	optional bool testgen_all = 63015;
+	optional bool benchgen_all = 63016;
+	optional bool marshaler_all = 63017;
+	optional bool unmarshaler_all = 63018;
+	optional bool stable_marshaler_all = 63019;
+
+	optional bool sizer_all = 63020;
+
+	optional bool goproto_enum_stringer_all = 63021;
+	optional bool enum_stringer_all = 63022;
+
+	optional bool unsafe_marshaler_all = 63023;
+	optional bool unsafe_unmarshaler_all = 63024;
+
+	optional bool goproto_extensions_map_all = 63025;
+	optional bool goproto_unrecognized_all = 63026;
+	optional bool gogoproto_import = 63027;
+	optional bool protosizer_all = 63028;
+	optional bool compare_all = 63029;
+    optional bool typedecl_all = 63030;
+    optional bool enumdecl_all = 63031;
+
+	optional bool goproto_registration = 63032;
+	optional bool messagename_all = 63033;
+
+	optional bool goproto_sizecache_all = 63034;
+	optional bool goproto_unkeyed_all = 63035;
+}
+
+extend google.protobuf.MessageOptions {
+	optional bool goproto_getters = 64001;
+	optional bool goproto_stringer = 64003;
+	optional bool verbose_equal = 64004;
+	optional bool face = 64005;
+	optional bool gostring = 64006;
+	optional bool populate = 64007;
+	optional bool stringer = 67008;
+	optional bool onlyone = 64009;
+
+	optional bool equal = 64013;
+	optional bool description = 64014;
+	optional bool testgen = 64015;
+	optional bool benchgen = 64016;
+	optional bool marshaler = 64017;
+	optional bool unmarshaler = 64018;
+	optional bool stable_marshaler = 64019;
+
+	optional bool sizer = 64020;
+
+	optional bool unsafe_marshaler = 64023;
+	optional bool unsafe_unmarshaler = 64024;
+
+	optional bool goproto_extensions_map = 64025;
+	optional bool goproto_unrecognized = 64026;
+
+	optional bool protosizer = 64028;
+	optional bool compare = 64029;
+
+	optional bool typedecl = 64030;
+
+	optional bool messagename = 64033;
+
+	optional bool goproto_sizecache = 64034;
+	optional bool goproto_unkeyed = 64035;
+}
+
+extend google.protobuf.FieldOptions {
+	optional bool nullable = 65001;
+	optional bool embed = 65002;
+	optional string customtype = 65003;
+	optional string customname = 65004;
+	optional string jsontag = 65005;
+	optional string moretags = 65006;
+	optional string casttype = 65007;
+	optional string castkey = 65008;
+	optional string castvalue = 65009;
+
+	optional bool stdtime = 65010;
+	optional bool stdduration = 65011;
+	optional bool wktpointer = 65012;
+
+}
diff --git a/encoding/protobuf/testdata/google/protobuf/any.proto b/encoding/protobuf/testdata/google/protobuf/any.proto
index 4cf3843..c9be854 100644
--- a/encoding/protobuf/testdata/google/protobuf/any.proto
+++ b/encoding/protobuf/testdata/google/protobuf/any.proto
@@ -33,7 +33,7 @@
 package google.protobuf;
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option go_package = "types";
+option go_package = "github.com/golang/protobuf/ptypes/any";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "AnyProto";
 option java_multiple_files = true;
diff --git a/encoding/protobuf/testdata/google/protobuf/api.proto b/encoding/protobuf/testdata/google/protobuf/api.proto
deleted file mode 100644
index 67c1ddb..0000000
--- a/encoding/protobuf/testdata/google/protobuf/api.proto
+++ /dev/null
@@ -1,210 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package google.protobuf;
-
-import "google/protobuf/source_context.proto";
-import "google/protobuf/type.proto";
-
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option java_package = "com.google.protobuf";
-option java_outer_classname = "ApiProto";
-option java_multiple_files = true;
-option objc_class_prefix = "GPB";
-option go_package = "types";
-
-// Api is a light-weight descriptor for an API Interface.
-//
-// Interfaces are also described as "protocol buffer services" in some contexts,
-// such as by the "service" keyword in a .proto file, but they are different
-// from API Services, which represent a concrete implementation of an interface
-// as opposed to simply a description of methods and bindings. They are also
-// sometimes simply referred to as "APIs" in other contexts, such as the name of
-// this message itself. See https://cloud.google.com/apis/design/glossary for
-// detailed terminology.
-message Api {
-
-  // The fully qualified name of this interface, including package name
-  // followed by the interface's simple name.
-  string name = 1;
-
-  // The methods of this interface, in unspecified order.
-  repeated Method methods = 2;
-
-  // Any metadata attached to the interface.
-  repeated Option options = 3;
-
-  // A version string for this interface. If specified, must have the form
-  // `major-version.minor-version`, as in `1.10`. If the minor version is
-  // omitted, it defaults to zero. If the entire version field is empty, the
-  // major version is derived from the package name, as outlined below. If the
-  // field is not empty, the version in the package name will be verified to be
-  // consistent with what is provided here.
-  //
-  // The versioning schema uses [semantic
-  // versioning](http://semver.org) where the major version number
-  // indicates a breaking change and the minor version an additive,
-  // non-breaking change. Both version numbers are signals to users
-  // what to expect from different versions, and should be carefully
-  // chosen based on the product plan.
-  //
-  // The major version is also reflected in the package name of the
-  // interface, which must end in `v<major-version>`, as in
-  // `google.feature.v1`. For major versions 0 and 1, the suffix can
-  // be omitted. Zero major versions must only be used for
-  // experimental, non-GA interfaces.
-  //
-  //
-  string version = 4;
-
-  // Source context for the protocol buffer service represented by this
-  // message.
-  SourceContext source_context = 5;
-
-  // Included interfaces. See [Mixin][].
-  repeated Mixin mixins = 6;
-
-  // The source syntax of the service.
-  Syntax syntax = 7;
-}
-
-// Method represents a method of an API interface.
-message Method {
-
-  // The simple name of this method.
-  string name = 1;
-
-  // A URL of the input message type.
-  string request_type_url = 2;
-
-  // If true, the request is streamed.
-  bool request_streaming = 3;
-
-  // The URL of the output message type.
-  string response_type_url = 4;
-
-  // If true, the response is streamed.
-  bool response_streaming = 5;
-
-  // Any metadata attached to the method.
-  repeated Option options = 6;
-
-  // The source syntax of this method.
-  Syntax syntax = 7;
-}
-
-// Declares an API Interface to be included in this interface. The including
-// interface must redeclare all the methods from the included interface, but
-// documentation and options are inherited as follows:
-//
-// - If after comment and whitespace stripping, the documentation
-//   string of the redeclared method is empty, it will be inherited
-//   from the original method.
-//
-// - Each annotation belonging to the service config (http,
-//   visibility) which is not set in the redeclared method will be
-//   inherited.
-//
-// - If an http annotation is inherited, the path pattern will be
-//   modified as follows. Any version prefix will be replaced by the
-//   version of the including interface plus the [root][] path if
-//   specified.
-//
-// Example of a simple mixin:
-//
-//     package google.acl.v1;
-//     service AccessControl {
-//       // Get the underlying ACL object.
-//       rpc GetAcl(GetAclRequest) returns (Acl) {
-//         option (google.api.http).get = "/v1/{resource=**}:getAcl";
-//       }
-//     }
-//
-//     package google.storage.v2;
-//     service Storage {
-//       rpc GetAcl(GetAclRequest) returns (Acl);
-//
-//       // Get a data record.
-//       rpc GetData(GetDataRequest) returns (Data) {
-//         option (google.api.http).get = "/v2/{resource=**}";
-//       }
-//     }
-//
-// Example of a mixin configuration:
-//
-//     apis:
-//     - name: google.storage.v2.Storage
-//       mixins:
-//       - name: google.acl.v1.AccessControl
-//
-// The mixin construct implies that all methods in `AccessControl` are
-// also declared with same name and request/response types in
-// `Storage`. A documentation generator or annotation processor will
-// see the effective `Storage.GetAcl` method after inherting
-// documentation and annotations as follows:
-//
-//     service Storage {
-//       // Get the underlying ACL object.
-//       rpc GetAcl(GetAclRequest) returns (Acl) {
-//         option (google.api.http).get = "/v2/{resource=**}:getAcl";
-//       }
-//       ...
-//     }
-//
-// Note how the version in the path pattern changed from `v1` to `v2`.
-//
-// If the `root` field in the mixin is specified, it should be a
-// relative path under which inherited HTTP paths are placed. Example:
-//
-//     apis:
-//     - name: google.storage.v2.Storage
-//       mixins:
-//       - name: google.acl.v1.AccessControl
-//         root: acls
-//
-// This implies the following inherited HTTP annotation:
-//
-//     service Storage {
-//       // Get the underlying ACL object.
-//       rpc GetAcl(GetAclRequest) returns (Acl) {
-//         option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
-//       }
-//       ...
-//     }
-message Mixin {
-  // The fully qualified name of the interface which is included.
-  string name = 1;
-
-  // If non-empty specifies a path under which inherited HTTP paths
-  // are rooted.
-  string root = 2;
-}
diff --git a/encoding/protobuf/testdata/google/protobuf/compiler/plugin.proto b/encoding/protobuf/testdata/google/protobuf/compiler/plugin.proto
deleted file mode 100644
index e85c852..0000000
--- a/encoding/protobuf/testdata/google/protobuf/compiler/plugin.proto
+++ /dev/null
@@ -1,167 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: kenton@google.com (Kenton Varda)
-//
-// WARNING:  The plugin interface is currently EXPERIMENTAL and is subject to
-//   change.
-//
-// protoc (aka the Protocol Compiler) can be extended via plugins.  A plugin is
-// just a program that reads a CodeGeneratorRequest from stdin and writes a
-// CodeGeneratorResponse to stdout.
-//
-// Plugins written using C++ can use google/protobuf/compiler/plugin.h instead
-// of dealing with the raw protocol defined here.
-//
-// A plugin executable needs only to be placed somewhere in the path.  The
-// plugin should be named "protoc-gen-$NAME", and will then be used when the
-// flag "--${NAME}_out" is passed to protoc.
-
-syntax = "proto2";
-package google.protobuf.compiler;
-option java_package = "com.google.protobuf.compiler";
-option java_outer_classname = "PluginProtos";
-
-option go_package = "plugin_go";
-
-import "google/protobuf/descriptor.proto";
-
-// The version number of protocol compiler.
-message Version {
-  optional int32 major = 1;
-  optional int32 minor = 2;
-  optional int32 patch = 3;
-  // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
-  // be empty for mainline stable releases.
-  optional string suffix = 4;
-}
-
-// An encoded CodeGeneratorRequest is written to the plugin's stdin.
-message CodeGeneratorRequest {
-  // The .proto files that were explicitly listed on the command-line.  The
-  // code generator should generate code only for these files.  Each file's
-  // descriptor will be included in proto_file, below.
-  repeated string file_to_generate = 1;
-
-  // The generator parameter passed on the command-line.
-  optional string parameter = 2;
-
-  // FileDescriptorProtos for all files in files_to_generate and everything
-  // they import.  The files will appear in topological order, so each file
-  // appears before any file that imports it.
-  //
-  // protoc guarantees that all proto_files will be written after
-  // the fields above, even though this is not technically guaranteed by the
-  // protobuf wire format.  This theoretically could allow a plugin to stream
-  // in the FileDescriptorProtos and handle them one by one rather than read
-  // the entire set into memory at once.  However, as of this writing, this
-  // is not similarly optimized on protoc's end -- it will store all fields in
-  // memory at once before sending them to the plugin.
-  //
-  // Type names of fields and extensions in the FileDescriptorProto are always
-  // fully qualified.
-  repeated FileDescriptorProto proto_file = 15;
-
-  // The version number of protocol compiler.
-  optional Version compiler_version = 3;
-
-}
-
-// The plugin writes an encoded CodeGeneratorResponse to stdout.
-message CodeGeneratorResponse {
-  // Error message.  If non-empty, code generation failed.  The plugin process
-  // should exit with status code zero even if it reports an error in this way.
-  //
-  // This should be used to indicate errors in .proto files which prevent the
-  // code generator from generating correct code.  Errors which indicate a
-  // problem in protoc itself -- such as the input CodeGeneratorRequest being
-  // unparseable -- should be reported by writing a message to stderr and
-  // exiting with a non-zero status code.
-  optional string error = 1;
-
-  // Represents a single generated file.
-  message File {
-    // The file name, relative to the output directory.  The name must not
-    // contain "." or ".." components and must be relative, not be absolute (so,
-    // the file cannot lie outside the output directory).  "/" must be used as
-    // the path separator, not "\".
-    //
-    // If the name is omitted, the content will be appended to the previous
-    // file.  This allows the generator to break large files into small chunks,
-    // and allows the generated text to be streamed back to protoc so that large
-    // files need not reside completely in memory at one time.  Note that as of
-    // this writing protoc does not optimize for this -- it will read the entire
-    // CodeGeneratorResponse before writing files to disk.
-    optional string name = 1;
-
-    // If non-empty, indicates that the named file should already exist, and the
-    // content here is to be inserted into that file at a defined insertion
-    // point.  This feature allows a code generator to extend the output
-    // produced by another code generator.  The original generator may provide
-    // insertion points by placing special annotations in the file that look
-    // like:
-    //   @@protoc_insertion_point(NAME)
-    // The annotation can have arbitrary text before and after it on the line,
-    // which allows it to be placed in a comment.  NAME should be replaced with
-    // an identifier naming the point -- this is what other generators will use
-    // as the insertion_point.  Code inserted at this point will be placed
-    // immediately above the line containing the insertion point (thus multiple
-    // insertions to the same point will come out in the order they were added).
-    // The double-@ is intended to make it unlikely that the generated code
-    // could contain things that look like insertion points by accident.
-    //
-    // For example, the C++ code generator places the following line in the
-    // .pb.h files that it generates:
-    //   // @@protoc_insertion_point(namespace_scope)
-    // This line appears within the scope of the file's package namespace, but
-    // outside of any particular class.  Another plugin can then specify the
-    // insertion_point "namespace_scope" to generate additional classes or
-    // other declarations that should be placed in this scope.
-    //
-    // Note that if the line containing the insertion point begins with
-    // whitespace, the same whitespace will be added to every line of the
-    // inserted text.  This is useful for languages like Python, where
-    // indentation matters.  In these languages, the insertion point comment
-    // should be indented the same amount as any inserted code will need to be
-    // in order to work correctly in that context.
-    //
-    // The code generator that generates the initial file and the one which
-    // inserts into it must both run as part of a single invocation of protoc.
-    // Code generators are executed in the order in which they appear on the
-    // command line.
-    //
-    // If |insertion_point| is present, |name| must also be present.
-    optional string insertion_point = 2;
-
-    // The file contents.
-    optional string content = 15;
-  }
-  repeated File file = 15;
-}
diff --git a/encoding/protobuf/testdata/google/protobuf/descriptor.proto b/encoding/protobuf/testdata/google/protobuf/descriptor.proto
index 887f16d..a2102d7 100644
--- a/encoding/protobuf/testdata/google/protobuf/descriptor.proto
+++ b/encoding/protobuf/testdata/google/protobuf/descriptor.proto
@@ -40,7 +40,8 @@
 syntax = "proto2";
 
 package google.protobuf;
-option go_package = "descriptor";
+
+option go_package = "github.com/golang/protobuf/protoc-gen-go/descriptor;descriptor";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "DescriptorProtos";
 option csharp_namespace = "Google.Protobuf.Reflection";
@@ -59,8 +60,8 @@
 
 // Describes a complete .proto file.
 message FileDescriptorProto {
-  optional string name = 1;       // file name, relative to root of source tree
-  optional string package = 2;    // e.g. "foo", "foo.bar", etc.
+  optional string name = 1;     // file name, relative to root of source tree
+  optional string package = 2;  // e.g. "foo", "foo.bar", etc.
 
   // Names of files imported by this file.
   repeated string dependency = 3;
@@ -100,8 +101,8 @@
   repeated EnumDescriptorProto enum_type = 4;
 
   message ExtensionRange {
-    optional int32 start = 1;
-    optional int32 end = 2;
+    optional int32 start = 1;  // Inclusive.
+    optional int32 end = 2;    // Exclusive.
 
     optional ExtensionRangeOptions options = 3;
   }
@@ -115,8 +116,8 @@
   // fields or extension ranges in the same message. Reserved ranges may
   // not overlap.
   message ReservedRange {
-    optional int32 start = 1; // Inclusive.
-    optional int32 end = 2;   // Exclusive.
+    optional int32 start = 1;  // Inclusive.
+    optional int32 end = 2;    // Exclusive.
   }
   repeated ReservedRange reserved_range = 9;
   // Reserved field names, which may not be used by fields in the same message.
@@ -137,42 +138,42 @@
   enum Type {
     // 0 is reserved for errors.
     // Order is weird for historical reasons.
-    TYPE_DOUBLE         = 1;
-    TYPE_FLOAT          = 2;
+    TYPE_DOUBLE = 1;
+    TYPE_FLOAT = 2;
     // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
     // negative values are likely.
-    TYPE_INT64          = 3;
-    TYPE_UINT64         = 4;
+    TYPE_INT64 = 3;
+    TYPE_UINT64 = 4;
     // Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
     // negative values are likely.
-    TYPE_INT32          = 5;
-    TYPE_FIXED64        = 6;
-    TYPE_FIXED32        = 7;
-    TYPE_BOOL           = 8;
-    TYPE_STRING         = 9;
+    TYPE_INT32 = 5;
+    TYPE_FIXED64 = 6;
+    TYPE_FIXED32 = 7;
+    TYPE_BOOL = 8;
+    TYPE_STRING = 9;
     // Tag-delimited aggregate.
     // Group type is deprecated and not supported in proto3. However, Proto3
     // implementations should still be able to parse the group wire format and
     // treat group fields as unknown fields.
-    TYPE_GROUP          = 10;
-    TYPE_MESSAGE        = 11;  // Length-delimited aggregate.
+    TYPE_GROUP = 10;
+    TYPE_MESSAGE = 11;  // Length-delimited aggregate.
 
     // New in version 2.
-    TYPE_BYTES          = 12;
-    TYPE_UINT32         = 13;
-    TYPE_ENUM           = 14;
-    TYPE_SFIXED32       = 15;
-    TYPE_SFIXED64       = 16;
-    TYPE_SINT32         = 17;  // Uses ZigZag encoding.
-    TYPE_SINT64         = 18;  // Uses ZigZag encoding.
-  };
+    TYPE_BYTES = 12;
+    TYPE_UINT32 = 13;
+    TYPE_ENUM = 14;
+    TYPE_SFIXED32 = 15;
+    TYPE_SFIXED64 = 16;
+    TYPE_SINT32 = 17;  // Uses ZigZag encoding.
+    TYPE_SINT64 = 18;  // Uses ZigZag encoding.
+  }
 
   enum Label {
     // 0 is reserved for errors
-    LABEL_OPTIONAL      = 1;
-    LABEL_REQUIRED      = 2;
-    LABEL_REPEATED      = 3;
-  };
+    LABEL_OPTIONAL = 1;
+    LABEL_REQUIRED = 2;
+    LABEL_REPEATED = 3;
+  }
 
   optional string name = 1;
   optional int32 number = 3;
@@ -234,8 +235,8 @@
   // is inclusive such that it can appropriately represent the entire int32
   // domain.
   message EnumReservedRange {
-    optional int32 start = 1; // Inclusive.
-    optional int32 end = 2;   // Inclusive.
+    optional int32 start = 1;  // Inclusive.
+    optional int32 end = 2;    // Inclusive.
   }
 
   // Range of reserved numeric values. Reserved numeric values may not be used
@@ -276,9 +277,9 @@
   optional MethodOptions options = 4;
 
   // Identifies if client streams multiple client messages
-  optional bool client_streaming = 5 [default=false];
+  optional bool client_streaming = 5 [default = false];
   // Identifies if server streams multiple server messages
-  optional bool server_streaming = 6 [default=false];
+  optional bool server_streaming = 6 [default = false];
 }
 
 
@@ -314,7 +315,6 @@
 //   If this turns out to be popular, a web service will be set up
 //   to automatically assign option numbers.
 
-
 message FileOptions {
 
   // Sets the Java package where classes generated from this .proto will be
@@ -337,7 +337,7 @@
   // named by java_outer_classname.  However, the outer class will still be
   // generated to contain the file's getDescriptor() method as well as any
   // top-level extensions defined in the file.
-  optional bool java_multiple_files = 10 [default=false];
+  optional bool java_multiple_files = 10 [default = false];
 
   // This option does nothing.
   optional bool java_generate_equals_and_hash = 20 [deprecated=true];
@@ -348,17 +348,17 @@
   // Message reflection will do the same.
   // However, an extension field still accepts non-UTF-8 byte sequences.
   // This option has no effect on when used with the lite runtime.
-  optional bool java_string_check_utf8 = 27 [default=false];
+  optional bool java_string_check_utf8 = 27 [default = false];
 
 
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
-    SPEED = 1;        // Generate complete code for parsing, serialization,
-                      // etc.
-    CODE_SIZE = 2;    // Use ReflectionOps to implement these methods.
-    LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime.
+    SPEED = 1;         // Generate complete code for parsing, serialization,
+                       // etc.
+    CODE_SIZE = 2;     // Use ReflectionOps to implement these methods.
+    LITE_RUNTIME = 3;  // Generate code using MessageLite and the lite runtime.
   }
-  optional OptimizeMode optimize_for = 9 [default=SPEED];
+  optional OptimizeMode optimize_for = 9 [default = SPEED];
 
   // Sets the Go package where structs generated from this .proto will be
   // placed. If omitted, the Go package will be derived from the following:
@@ -369,6 +369,7 @@
 
 
 
+
   // Should generic services be generated in each language?  "Generic" services
   // are not specific to any particular RPC system.  They are generated by the
   // main code generators in each language (without additional plugins).
@@ -379,20 +380,20 @@
   // that generate code specific to your particular RPC system.  Therefore,
   // these default to false.  Old code which depends on generic services should
   // explicitly set them to true.
-  optional bool cc_generic_services = 16 [default=false];
-  optional bool java_generic_services = 17 [default=false];
-  optional bool py_generic_services = 18 [default=false];
-  optional bool php_generic_services = 42 [default=false];
+  optional bool cc_generic_services = 16 [default = false];
+  optional bool java_generic_services = 17 [default = false];
+  optional bool py_generic_services = 18 [default = false];
+  optional bool php_generic_services = 42 [default = false];
 
   // Is this file deprecated?
   // Depending on the target platform, this can emit Deprecated annotations
   // for everything in the file, or it will be completely ignored; in the very
   // least, this is a formalization for deprecating files.
-  optional bool deprecated = 23 [default=false];
+  optional bool deprecated = 23 [default = false];
 
   // Enables the use of arenas for the proto messages in this file. This applies
   // only to generated classes for C++.
-  optional bool cc_enable_arenas = 31 [default=false];
+  optional bool cc_enable_arenas = 31 [default = false];
 
 
   // Sets the objective c class prefix which is prepended to all objective c
@@ -417,10 +418,9 @@
   // determining the namespace.
   optional string php_namespace = 41;
 
-
   // Use this option to change the namespace of php generated metadata classes.
-  // Default is empty. When this option is empty, the proto file name will be used
-  // for determining the namespace.
+  // Default is empty. When this option is empty, the proto file name will be
+  // used for determining the namespace.
   optional string php_metadata_namespace = 44;
 
   // Use this option to change the package of ruby generated classes. Default
@@ -428,6 +428,7 @@
   // determining the ruby package.
   optional string ruby_package = 45;
 
+
   // The parser stores options it doesn't recognize here.
   // See the documentation for the "Options" section above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -436,7 +437,7 @@
   // See the documentation for the "Options" section above.
   extensions 1000 to max;
 
-  //reserved 38;
+  reserved 38;
 }
 
 message MessageOptions {
@@ -458,18 +459,18 @@
   //
   // Because this is an option, the above two restrictions are not enforced by
   // the protocol compiler.
-  optional bool message_set_wire_format = 1 [default=false];
+  optional bool message_set_wire_format = 1 [default = false];
 
   // Disables the generation of the standard "descriptor()" accessor, which can
   // conflict with a field of the same name.  This is meant to make migration
   // from proto1 easier; new code should avoid fields named "descriptor".
-  optional bool no_standard_descriptor_accessor = 2 [default=false];
+  optional bool no_standard_descriptor_accessor = 2 [default = false];
 
   // Is this message deprecated?
   // Depending on the target platform, this can emit Deprecated annotations
   // for the message, or it will be completely ignored; in the very least,
   // this is a formalization for deprecating messages.
-  optional bool deprecated = 3 [default=false];
+  optional bool deprecated = 3 [default = false];
 
   // Whether the message is an automatically generated map entry type for the
   // maps field.
@@ -486,7 +487,7 @@
   //
   // Implementations may choose not to generate the map_entry=true message, but
   // use a native map in the target language to hold the keys and values.
-  // The reflection APIs in such implementions still need to work as
+  // The reflection APIs in such implementations still need to work as
   // if the field is a repeated message field.
   //
   // NOTE: Do not set the option in .proto files. Always use the maps syntax
@@ -494,8 +495,9 @@
   // parser.
   optional bool map_entry = 7;
 
-  //reserved 8;  // javalite_serializable
-  //reserved 9;  // javanano_as_lite
+  reserved 8;  // javalite_serializable
+  reserved 9;  // javanano_as_lite
+
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -576,16 +578,16 @@
   // implementation must either *always* check its required fields, or *never*
   // check its required fields, regardless of whether or not the message has
   // been parsed.
-  optional bool lazy = 5 [default=false];
+  optional bool lazy = 5 [default = false];
 
   // Is this field deprecated?
   // Depending on the target platform, this can emit Deprecated annotations
   // for accessors, or it will be completely ignored; in the very least, this
   // is a formalization for deprecating fields.
-  optional bool deprecated = 3 [default=false];
+  optional bool deprecated = 3 [default = false];
 
   // For Google-internal migration only. Do not use.
-  optional bool weak = 10 [default=false];
+  optional bool weak = 10 [default = false];
 
 
   // The parser stores options it doesn't recognize here. See above.
@@ -594,7 +596,7 @@
   // Clients can define custom options in extensions of this message. See above.
   extensions 1000 to max;
 
-  //reserved 4;  // removed jtype
+  reserved 4;  // removed jtype
 }
 
 message OneofOptions {
@@ -615,9 +617,9 @@
   // Depending on the target platform, this can emit Deprecated annotations
   // for the enum, or it will be completely ignored; in the very least, this
   // is a formalization for deprecating enums.
-  optional bool deprecated = 3 [default=false];
+  optional bool deprecated = 3 [default = false];
 
-  //reserved 5;  // javanano_as_lite
+  reserved 5;  // javanano_as_lite
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -631,7 +633,7 @@
   // Depending on the target platform, this can emit Deprecated annotations
   // for the enum value, or it will be completely ignored; in the very least,
   // this is a formalization for deprecating enum values.
-  optional bool deprecated = 1 [default=false];
+  optional bool deprecated = 1 [default = false];
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -651,7 +653,7 @@
   // Depending on the target platform, this can emit Deprecated annotations
   // for the service, or it will be completely ignored; in the very least,
   // this is a formalization for deprecating services.
-  optional bool deprecated = 33 [default=false];
+  optional bool deprecated = 33 [default = false];
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -671,18 +673,18 @@
   // Depending on the target platform, this can emit Deprecated annotations
   // for the method, or it will be completely ignored; in the very least,
   // this is a formalization for deprecating methods.
-  optional bool deprecated = 33 [default=false];
+  optional bool deprecated = 33 [default = false];
 
   // Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
   // or neither? HTTP based RPC implementation may choose GET verb for safe
   // methods, and PUT verb for idempotent methods instead of the default POST.
   enum IdempotencyLevel {
     IDEMPOTENCY_UNKNOWN = 0;
-    NO_SIDE_EFFECTS     = 1; // implies idempotent
-    IDEMPOTENT          = 2; // idempotent, but may have side effects
+    NO_SIDE_EFFECTS = 1;  // implies idempotent
+    IDEMPOTENT = 2;       // idempotent, but may have side effects
   }
-  optional IdempotencyLevel idempotency_level =
-      34 [default=IDEMPOTENCY_UNKNOWN];
+  optional IdempotencyLevel idempotency_level = 34
+      [default = IDEMPOTENCY_UNKNOWN];
 
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -763,7 +765,7 @@
   //   beginning of the "extend" block and is shared by all extensions within
   //   the block.
   // - Just because a location's span is a subset of some other location's span
-  //   does not mean that it is a descendent.  For example, a "group" defines
+  //   does not mean that it is a descendant.  For example, a "group" defines
   //   both a type and a field in a single declaration.  Thus, the locations
   //   corresponding to the type and field and their components will overlap.
   // - Code which tries to interpret locations should probably be designed to
@@ -794,14 +796,14 @@
     //   [ 4, 3, 2, 7 ]
     // this path refers to the whole field declaration (from the beginning
     // of the label to the terminating semicolon).
-    repeated int32 path = 1 [packed=true];
+    repeated int32 path = 1 [packed = true];
 
     // Always has exactly three or four elements: start line, start column,
     // end line (optional, otherwise assumed same as start line), end column.
     // These are packed into a single field for efficiency.  Note that line
     // and column numbers are zero-based -- typically you will want to add
     // 1 to each before displaying to a user.
-    repeated int32 span = 2 [packed=true];
+    repeated int32 span = 2 [packed = true];
 
     // If this SourceCodeInfo represents a complete declaration, these are any
     // comments appearing before and after the declaration which appear to be
@@ -866,7 +868,7 @@
   message Annotation {
     // Identifies the element in the original source .proto file. This field
     // is formatted the same as SourceCodeInfo.Location.path.
-    repeated int32 path = 1 [packed=true];
+    repeated int32 path = 1 [packed = true];
 
     // Identifies the filesystem path to the original source .proto.
     optional string source_file = 2;
diff --git a/encoding/protobuf/testdata/google/protobuf/duration.proto b/encoding/protobuf/testdata/google/protobuf/duration.proto
index 8bbaa8b..9d8a52d 100644
--- a/encoding/protobuf/testdata/google/protobuf/duration.proto
+++ b/encoding/protobuf/testdata/google/protobuf/duration.proto
@@ -34,7 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "types";
+option go_package = "github.com/golang/protobuf/ptypes/duration";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "DurationProto";
 option java_multiple_files = true;
@@ -101,7 +101,6 @@
 //
 //
 message Duration {
-
   // Signed seconds of the span of time. Must be from -315,576,000,000
   // to +315,576,000,000 inclusive. Note: these bounds are computed from:
   // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
diff --git a/encoding/protobuf/testdata/google/protobuf/field_mask.proto b/encoding/protobuf/testdata/google/protobuf/field_mask.proto
deleted file mode 100644
index 7b77007..0000000
--- a/encoding/protobuf/testdata/google/protobuf/field_mask.proto
+++ /dev/null
@@ -1,245 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package google.protobuf;
-
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option java_package = "com.google.protobuf";
-option java_outer_classname = "FieldMaskProto";
-option java_multiple_files = true;
-option objc_class_prefix = "GPB";
-option go_package = "types";
-option cc_enable_arenas = true;
-
-// `FieldMask` represents a set of symbolic field paths, for example:
-//
-//     paths: "f.a"
-//     paths: "f.b.d"
-//
-// Here `f` represents a field in some root message, `a` and `b`
-// fields in the message found in `f`, and `d` a field found in the
-// message in `f.b`.
-//
-// Field masks are used to specify a subset of fields that should be
-// returned by a get operation or modified by an update operation.
-// Field masks also have a custom JSON encoding (see below).
-//
-// # Field Masks in Projections
-//
-// When used in the context of a projection, a response message or
-// sub-message is filtered by the API to only contain those fields as
-// specified in the mask. For example, if the mask in the previous
-// example is applied to a response message as follows:
-//
-//     f {
-//       a : 22
-//       b {
-//         d : 1
-//         x : 2
-//       }
-//       y : 13
-//     }
-//     z: 8
-//
-// The result will not contain specific values for fields x,y and z
-// (their value will be set to the default, and omitted in proto text
-// output):
-//
-//
-//     f {
-//       a : 22
-//       b {
-//         d : 1
-//       }
-//     }
-//
-// A repeated field is not allowed except at the last position of a
-// paths string.
-//
-// If a FieldMask object is not present in a get operation, the
-// operation applies to all fields (as if a FieldMask of all fields
-// had been specified).
-//
-// Note that a field mask does not necessarily apply to the
-// top-level response message. In case of a REST get operation, the
-// field mask applies directly to the response, but in case of a REST
-// list operation, the mask instead applies to each individual message
-// in the returned resource list. In case of a REST custom method,
-// other definitions may be used. Where the mask applies will be
-// clearly documented together with its declaration in the API.  In
-// any case, the effect on the returned resource/resources is required
-// behavior for APIs.
-//
-// # Field Masks in Update Operations
-//
-// A field mask in update operations specifies which fields of the
-// targeted resource are going to be updated. The API is required
-// to only change the values of the fields as specified in the mask
-// and leave the others untouched. If a resource is passed in to
-// describe the updated values, the API ignores the values of all
-// fields not covered by the mask.
-//
-// If a repeated field is specified for an update operation, new values will
-// be appended to the existing repeated field in the target resource. Note that
-// a repeated field is only allowed in the last position of a `paths` string.
-//
-// If a sub-message is specified in the last position of the field mask for an
-// update operation, then new value will be merged into the existing sub-message
-// in the target resource.
-//
-// For example, given the target message:
-//
-//     f {
-//       b {
-//         d: 1
-//         x: 2
-//       }
-//       c: [1]
-//     }
-//
-// And an update message:
-//
-//     f {
-//       b {
-//         d: 10
-//       }
-//       c: [2]
-//     }
-//
-// then if the field mask is:
-//
-//  paths: ["f.b", "f.c"]
-//
-// then the result will be:
-//
-//     f {
-//       b {
-//         d: 10
-//         x: 2
-//       }
-//       c: [1, 2]
-//     }
-//
-// An implementation may provide options to override this default behavior for
-// repeated and message fields.
-//
-// In order to reset a field's value to the default, the field must
-// be in the mask and set to the default value in the provided resource.
-// Hence, in order to reset all fields of a resource, provide a default
-// instance of the resource and set all fields in the mask, or do
-// not provide a mask as described below.
-//
-// If a field mask is not present on update, the operation applies to
-// all fields (as if a field mask of all fields has been specified).
-// Note that in the presence of schema evolution, this may mean that
-// fields the client does not know and has therefore not filled into
-// the request will be reset to their default. If this is unwanted
-// behavior, a specific service may require a client to always specify
-// a field mask, producing an error if not.
-//
-// As with get operations, the location of the resource which
-// describes the updated values in the request message depends on the
-// operation kind. In any case, the effect of the field mask is
-// required to be honored by the API.
-//
-// ## Considerations for HTTP REST
-//
-// The HTTP kind of an update operation which uses a field mask must
-// be set to PATCH instead of PUT in order to satisfy HTTP semantics
-// (PUT must only be used for full updates).
-//
-// # JSON Encoding of Field Masks
-//
-// In JSON, a field mask is encoded as a single string where paths are
-// separated by a comma. Fields name in each path are converted
-// to/from lower-camel naming conventions.
-//
-// As an example, consider the following message declarations:
-//
-//     message Profile {
-//       User user = 1;
-//       Photo photo = 2;
-//     }
-//     message User {
-//       string display_name = 1;
-//       string address = 2;
-//     }
-//
-// In proto a field mask for `Profile` may look as such:
-//
-//     mask {
-//       paths: "user.display_name"
-//       paths: "photo"
-//     }
-//
-// In JSON, the same mask is represented as below:
-//
-//     {
-//       mask: "user.displayName,photo"
-//     }
-//
-// # Field Masks and Oneof Fields
-//
-// Field masks treat fields in oneofs just as regular fields. Consider the
-// following message:
-//
-//     message SampleMessage {
-//       oneof test_oneof {
-//         string name = 4;
-//         SubMessage sub_message = 9;
-//       }
-//     }
-//
-// The field mask can be:
-//
-//     mask {
-//       paths: "name"
-//     }
-//
-// Or:
-//
-//     mask {
-//       paths: "sub_message"
-//     }
-//
-// Note that oneof type names ("test_oneof" in this case) cannot be used in
-// paths.
-//
-// ## Field Mask Verification
-//
-// The implementation of any API method which has a FieldMask type field in the
-// request should verify the included field paths, and return an
-// `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
-message FieldMask {
-  // The set of field mask paths.
-  repeated string paths = 1;
-}
diff --git a/encoding/protobuf/testdata/google/protobuf/source_context.proto b/encoding/protobuf/testdata/google/protobuf/source_context.proto
deleted file mode 100644
index 8654578..0000000
--- a/encoding/protobuf/testdata/google/protobuf/source_context.proto
+++ /dev/null
@@ -1,48 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2008 Google Inc.  All rights reserved.
-// https://developers.google.com/protocol-buffers/
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-syntax = "proto3";
-
-package google.protobuf;
-
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
-option java_package = "com.google.protobuf";
-option java_outer_classname = "SourceContextProto";
-option java_multiple_files = true;
-option objc_class_prefix = "GPB";
-option go_package = "types";
-
-// `SourceContext` represents information about the source of a
-// protobuf element, like the file in which it is defined.
-message SourceContext {
-  // The path-qualified name of the .proto file that contained the associated
-  // protobuf element.  For example: `"google/protobuf/source_context.proto"`.
-  string file_name = 1;
-}
diff --git a/encoding/protobuf/testdata/google/protobuf/timestamp.proto b/encoding/protobuf/testdata/google/protobuf/timestamp.proto
index 18cb7c3..cd35786 100644
--- a/encoding/protobuf/testdata/google/protobuf/timestamp.proto
+++ b/encoding/protobuf/testdata/google/protobuf/timestamp.proto
@@ -34,7 +34,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "types";
+option go_package = "github.com/golang/protobuf/ptypes/timestamp";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "TimestampProto";
 option java_multiple_files = true;
@@ -113,17 +113,18 @@
 // 01:30 UTC on January 15, 2017.
 //
 // In JavaScript, one can convert a Date object to this format using the
-// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
+// standard
+// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
 // method. In Python, a standard `datetime.datetime` object can be converted
-// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
-// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
-// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
+// to this format using
+// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
+// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
+// the Joda Time's [`ISODateTimeFormat.dateTime()`](
 // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
 // ) to obtain a formatter capable of generating timestamps in this format.
 //
 //
 message Timestamp {
-
   // Represents seconds of UTC time since Unix epoch
   // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
   // 9999-12-31T23:59:59Z inclusive.
diff --git a/encoding/protobuf/testdata/google/protobuf/wrappers.proto b/encoding/protobuf/testdata/google/protobuf/wrappers.proto
index 59b76ac..9ee41e3 100644
--- a/encoding/protobuf/testdata/google/protobuf/wrappers.proto
+++ b/encoding/protobuf/testdata/google/protobuf/wrappers.proto
@@ -44,7 +44,7 @@
 
 option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
-option go_package = "types";
+option go_package = "github.com/golang/protobuf/ptypes/wrappers";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "WrappersProto";
 option java_multiple_files = true;
diff --git a/encoding/protobuf/testdata/google/rpc/status.proto b/encoding/protobuf/testdata/google/rpc/status.proto
new file mode 100644
index 0000000..b0daa36
--- /dev/null
+++ b/encoding/protobuf/testdata/google/rpc/status.proto
@@ -0,0 +1,94 @@
+// Copyright 2017 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package google.rpc;
+
+import "google/protobuf/any.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";
+option java_multiple_files = true;
+option java_outer_classname = "StatusProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+// The `Status` type defines a logical error model that is suitable for
+// different programming environments, including REST APIs and RPC APIs. It is
+// used by [gRPC](https://github.com/grpc). The error model is designed to be:
+//
+// - Simple to use and understand for most users
+// - Flexible enough to meet unexpected needs
+//
+// # Overview
+//
+// The `Status` message contains three pieces of data: error code, error
+// message, and error details. The error code should be an enum value of
+// [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
+// if needed.  The error message should be a developer-facing English message
+// that helps developers *understand* and *resolve* the error. If a localized
+// user-facing error message is needed, put the localized message in the error
+// details or localize it in the client. The optional error details may contain
+// arbitrary information about the error. There is a predefined set of error
+// detail types in the package `google.rpc` that can be used for common error
+// conditions.
+//
+// # Language mapping
+//
+// The `Status` message is the logical representation of the error model, but it
+// is not necessarily the actual wire format. When the `Status` message is
+// exposed in different client libraries and different wire protocols, it can be
+// mapped differently. For example, it will likely be mapped to some exceptions
+// in Java, but more likely mapped to some error codes in C.
+//
+// # Other uses
+//
+// The error model and the `Status` message can be used in a variety of
+// environments, either with or without APIs, to provide a
+// consistent developer experience across different environments.
+//
+// Example uses of this error model include:
+//
+// - Partial errors. If a service needs to return partial errors to the client,
+//     it may embed the `Status` in the normal response to indicate the partial
+//     errors.
+//
+// - Workflow errors. A typical workflow has multiple steps. Each step may
+//     have a `Status` message for error reporting.
+//
+// - Batch operations. If a client uses batch request and batch response, the
+//     `Status` message should be used directly inside batch response, one for
+//     each error sub-response.
+//
+// - Asynchronous operations. If an API call embeds asynchronous operation
+//     results in its response, the status of those operations should be
+//     represented directly using the `Status` message.
+//
+// - Logging. If some API errors are stored in logs, the message `Status` could
+//     be used directly after any stripping needed for security/privacy reasons.
+message Status {
+  // The status code, which should be an enum value of
+  // [google.rpc.Code][google.rpc.Code].
+  int32 code = 1;
+
+  // A developer-facing error message, which should be in English. Any
+  // user-facing error message should be localized and sent in the
+  // [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+  // by the client.
+  string message = 2;
+
+  // A list of messages that carry the error details.  There is a common set of
+  // message types for APIs to use.
+  repeated google.protobuf.Any details = 3;
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes.proto
new file mode 100644
index 0000000..32fa4fc
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes.proto
@@ -0,0 +1,148 @@
+// Copyright 2016 Istio Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+syntax = "proto3";
+
+package istio.mixer.v1;
+
+option go_package = "istio.io/api/mixer/v1";
+
+import "gogoproto/gogo.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+option (gogoproto.goproto_getters_all) = false;
+option (gogoproto.equal_all) = false;
+option (gogoproto.gostring_all) = false;
+option (gogoproto.stable_marshaler_all) = true;
+option cc_enable_arenas = true;
+
+// Attributes represents a set of typed name/value pairs. Many of Mixer's
+// API either consume and/or return attributes.
+//
+// Istio uses attributes to control the runtime behavior of services running in the service mesh.
+// Attributes are named and typed pieces of metadata describing ingress and egress traffic and the
+// environment this traffic occurs in. An Istio attribute carries a specific piece
+// of information such as the error code of an API request, the latency of an API request, or the
+// original IP address of a TCP connection. For example:
+//
+// ```yaml
+// request.path: xyz/abc
+// request.size: 234
+// request.time: 12:34:56.789 04/17/2017
+// source.ip: 192.168.0.1
+// target.service: example
+// ```
+//
+// A given Istio deployment has a fixed vocabulary of attributes that it understands.
+// The specific vocabulary is determined by the set of attribute producers being used
+// in the deployment. The primary attribute producer in Istio is Envoy, although
+// specialized Mixer adapters and services can also generate attributes.
+//
+// The common baseline set of attributes available in most Istio deployments is defined
+// [here](https://istio.io/docs/reference/config/policy-and-telemetry/attribute-vocabulary/).
+//
+// Attributes are strongly typed. The supported attribute types are defined by
+// [ValueType](https://github.com/istio/api/blob/master/policy/v1beta1/value_type.proto).
+// Each type of value is encoded into one of the so-called transport types present
+// in this message.
+//
+// Defines a map of attributes in uncompressed format.
+// Following places may use this message:
+// 1) Configure Istio/Proxy with static per-proxy attributes, such as source.uid.
+// 2) Service IDL definition to extract api attributes for active requests.
+// 3) Forward attributes from client proxy to server proxy for HTTP requests.
+message Attributes {
+  // A map of attribute name to its value.
+  map<string, AttributeValue> attributes = 1;
+
+  // Specifies one attribute value with different type.
+  message AttributeValue {
+    // The attribute value.
+    oneof value {
+      // Used for values of type STRING, DNS_NAME, EMAIL_ADDRESS, and URI
+      string string_value = 2;
+
+      // Used for values of type INT64
+      int64 int64_value = 3;
+
+      // Used for values of type DOUBLE
+      double double_value = 4;
+
+      // Used for values of type BOOL
+      bool bool_value = 5;
+
+      // Used for values of type BYTES
+      bytes bytes_value = 6;
+
+      // Used for values of type TIMESTAMP
+      google.protobuf.Timestamp timestamp_value = 7;
+
+      // Used for values of type DURATION
+      google.protobuf.Duration duration_value = 8;
+
+      // Used for values of type STRING_MAP
+      StringMap string_map_value = 9;
+    }
+  }
+
+  // Defines a string map.
+  message StringMap {
+    // Holds a set of name/value pairs.
+    map<string, string> entries = 1;
+  }
+}
+
+// Defines a list of attributes in compressed format optimized for transport.
+// Within this message, strings are referenced using integer indices into
+// one of two string dictionaries. Positive integers index into the global
+// deployment-wide dictionary, whereas negative integers index into the message-level
+// dictionary instead. The message-level dictionary is carried by the
+// `words` field of this message, the deployment-wide dictionary is determined via
+// configuration.
+message CompressedAttributes {
+  // The message-level dictionary.
+  repeated string words = 1;
+
+  // Holds attributes of type STRING, DNS_NAME, EMAIL_ADDRESS, URI
+  map<sint32, sint32> strings = 2;
+
+  // Holds attributes of type INT64
+  map<sint32, int64> int64s = 3;
+
+  // Holds attributes of type DOUBLE
+  map<sint32, double> doubles = 4;
+
+  // Holds attributes of type BOOL
+  map<sint32, bool> bools = 5;
+
+  // Holds attributes of type TIMESTAMP
+  map<sint32, google.protobuf.Timestamp> timestamps = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
+
+  // Holds attributes of type DURATION
+  map<sint32, google.protobuf.Duration> durations = 7 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
+
+  // Holds attributes of type BYTES
+  map<sint32, bytes> bytes = 8;
+
+  // Holds attributes of type STRING_MAP
+  map<sint32, StringMap> string_maps = 9 [(gogoproto.nullable) = false];
+}
+
+// A map of string to string. The keys and values in this map are dictionary
+// indices (see the [Attributes][istio.mixer.v1.CompressedAttributes] message for an explanation)
+message StringMap {
+  // Holds a set of name/value pairs.
+  map<sint32, sint32> entries = 1;
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes_proto_gen.cue
new file mode 100644
index 0000000..73f70ad
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/attributes_proto_gen.cue
@@ -0,0 +1,136 @@
+
+//  Copyright 2016 Istio Authors
+// 
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+// 
+//      http://www.apache.org/licenses/LICENSE-2.0
+// 
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+package v1
+
+import "time"
+
+//  Attributes represents a set of typed name/value pairs. Many of Mixer's
+//  API either consume and/or return attributes.
+// 
+//  Istio uses attributes to control the runtime behavior of services running in the service mesh.
+//  Attributes are named and typed pieces of metadata describing ingress and egress traffic and the
+//  environment this traffic occurs in. An Istio attribute carries a specific piece
+//  of information such as the error code of an API request, the latency of an API request, or the
+//  original IP address of a TCP connection. For example:
+// 
+//  ```yaml
+//  request.path: xyz/abc
+//  request.size: 234
+//  request.time: 12:34:56.789 04/17/2017
+//  source.ip: 192.168.0.1
+//  target.service: example
+//  ```
+// 
+//  A given Istio deployment has a fixed vocabulary of attributes that it understands.
+//  The specific vocabulary is determined by the set of attribute producers being used
+//  in the deployment. The primary attribute producer in Istio is Envoy, although
+//  specialized Mixer adapters and services can also generate attributes.
+// 
+//  The common baseline set of attributes available in most Istio deployments is defined
+//  [here](https://istio.io/docs/reference/config/policy-and-telemetry/attribute-vocabulary/).
+// 
+//  Attributes are strongly typed. The supported attribute types are defined by
+//  [ValueType](https://github.com/istio/api/blob/master/policy/v1beta1/value_type.proto).
+//  Each type of value is encoded into one of the so-called transport types present
+//  in this message.
+// 
+//  Defines a map of attributes in uncompressed format.
+//  Following places may use this message:
+//  1) Configure Istio/Proxy with static per-proxy attributes, such as source.uid.
+//  2) Service IDL definition to extract api attributes for active requests.
+//  3) Forward attributes from client proxy to server proxy for HTTP requests.
+Attributes: {
+	//  A map of attribute name to its value.
+	attributes <_>: Attributes_AttributeValue
+}
+
+//  Specifies one attribute value with different type.
+Attributes_AttributeValue: {
+}
+//  The attribute value.
+Attributes_AttributeValue: {
+	//  Used for values of type STRING, DNS_NAME, EMAIL_ADDRESS, and URI
+	stringValue: string @protobuf(2,name=string_value)
+} | {
+	//  Used for values of type INT64
+	int64Value: int64 @protobuf(3,name=int64_value)
+} | {
+	//  Used for values of type DOUBLE
+	doubleValue: float64 @protobuf(4,type=double,name=double_value)
+} | {
+	//  Used for values of type BOOL
+	boolValue: bool @protobuf(5,name=bool_value)
+} | {
+	//  Used for values of type BYTES
+	bytesValue: bytes @protobuf(6,name=bytes_value)
+} | {
+	//  Used for values of type TIMESTAMP
+	timestampValue: time.Time @protobuf(7,type=google.protobuf.Timestamp,name=timestamp_value)
+} | {
+	//  Used for values of type DURATION
+	durationValue: time.Duration @protobuf(8,type=google.protobuf.Duration,name=duration_value)
+} | {
+	//  Used for values of type STRING_MAP
+	stringMapValue: Attributes_StringMap @protobuf(9,type=StringMap,name=string_map_value)
+}
+
+//  Defines a string map.
+Attributes_StringMap: {
+	//  Holds a set of name/value pairs.
+	entries <_>: string
+}
+
+//  Defines a list of attributes in compressed format optimized for transport.
+//  Within this message, strings are referenced using integer indices into
+//  one of two string dictionaries. Positive integers index into the global
+//  deployment-wide dictionary, whereas negative integers index into the message-level
+//  dictionary instead. The message-level dictionary is carried by the
+//  `words` field of this message, the deployment-wide dictionary is determined via
+//  configuration.
+CompressedAttributes: {
+	//  The message-level dictionary.
+	words?: [...string] @protobuf(1)
+
+	//  Holds attributes of type STRING, DNS_NAME, EMAIL_ADDRESS, URI
+	strings <_>: int32
+
+	//  Holds attributes of type INT64
+	int64s <_>: int64
+
+	//  Holds attributes of type DOUBLE
+	doubles <_>: float64
+
+	//  Holds attributes of type BOOL
+	bools <_>: bool
+
+	//  Holds attributes of type TIMESTAMP
+	timestamps <_>: time.Time
+
+	//  Holds attributes of type DURATION
+	durations <_>: time.Duration
+
+	//  Holds attributes of type BYTES
+	bytes <_>: bytes
+
+	//  Holds attributes of type STRING_MAP
+	stringMaps <_>: StringMap
+}
+
+//  A map of string to string. The keys and values in this map are dictionary
+//  indices (see the [Attributes][istio.mixer.v1.CompressedAttributes] message for an explanation)
+StringMap: {
+	//  Holds a set of name/value pairs.
+	entries <_>: int32
+}
diff --git a/encoding/protobuf/testdata/mixer/v1/config/client/api_spec.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/api_spec.proto
similarity index 100%
rename from encoding/protobuf/testdata/mixer/v1/config/client/api_spec.proto
rename to encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/api_spec.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/api_spec_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/api_spec_proto_gen.cue
new file mode 100644
index 0000000..3650de8
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/api_spec_proto_gen.cue
@@ -0,0 +1,228 @@
+
+//  Copyright 2017 Istio Authors
+// 
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+// 
+//        http://www.apache.org/licenses/LICENSE-2.0
+// 
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+package client
+
+import "istio.io/api/mixer/v1"
+
+//  HTTPAPISpec defines the canonical configuration for generating
+//  API-related attributes from HTTP requests based on the method and
+//  uri templated path matches. It is sufficient for defining the API
+//  surface of a service for the purposes of API attribute
+//  generation. It is not intended to represent auth, quota,
+//  documentation, or other information commonly found in other API
+//  specifications, e.g. OpenAPI.
+// 
+//  Existing standards that define operations (or methods) in terms of
+//  HTTP methods and paths can be normalized to this format for use in
+//  Istio. For example, a simple petstore API described by OpenAPIv2
+//  [here](https://github.com/googleapis/gnostic/blob/master/examples/v2.0/yaml/petstore-simple.yaml)
+//  can be represented with the following HTTPAPISpec.
+// 
+//  ```yaml
+//  apiVersion: config.istio.io/v1alpha2
+//  kind: HTTPAPISpec
+//  metadata:
+//    name: petstore
+//    namespace: default
+//  spec:
+//    attributes:
+//      attributes:
+//        api.service:
+//          stringValue: petstore.swagger.io
+//        api.version:
+//          stringValue: 1.0.0
+//    patterns:
+//    - attributes:
+//        attributes:
+//          api.operation:
+//            stringValue: findPets
+//      httpMethod: GET
+//      uriTemplate: /api/pets
+//    - attributes:
+//        attributes:
+//          api.operation:
+//            stringValue: addPet
+//      httpMethod: POST
+//      uriTemplate: /api/pets
+//    - attributes:
+//        attributes:
+//          api.operation:
+//            stringValue: findPetById
+//      httpMethod: GET
+//      uriTemplate: /api/pets/{id}
+//    - attributes:
+//        attributes:
+//          api.operation:
+//            stringValue: deletePet
+//      httpMethod: DELETE
+//      uriTemplate: /api/pets/{id}
+//    api_keys:
+//    - query: api-key
+//  ```
+HTTPAPISpec: {
+	//  List of attributes that are generated when *any* of the HTTP
+	//  patterns match. This list typically includes the "api.service"
+	//  and "api.version" attributes.
+	attributes?: v1.Attributes @protobuf(1,type=Attributes)
+
+	//  List of HTTP patterns to match.
+	patterns?: [...HTTPAPISpecPattern] @protobuf(2)
+
+	//  List of APIKey that describes how to extract an API-KEY from an
+	//  HTTP request. The first API-Key match found in the list is used,
+	//  i.e. 'OR' semantics.
+	// 
+	//  The following default policies are used to generate the
+	//  `request.api_key` attribute if no explicit APIKey is defined.
+	// 
+	//      `query: key, `query: api_key`, and then `header: x-api-key`
+	// 
+	apiKeys?: [...APIKey] @protobuf(3,name=api_keys)
+}
+
+//  HTTPAPISpecPattern defines a single pattern to match against
+//  incoming HTTP requests. The per-pattern list of attributes is
+//  generated if both the http_method and uri_template match. In
+//  addition, the top-level list of attributes in the HTTPAPISpec is also
+//  generated.
+// 
+//  ```yaml
+//  pattern:
+//  - attributes
+//      api.operation: doFooBar
+//    httpMethod: GET
+//    uriTemplate: /foo/bar
+//  ```
+HTTPAPISpecPattern: {
+	//  List of attributes that are generated if the HTTP request matches
+	//  the specified http_method and uri_template. This typically
+	//  includes the "api.operation" attribute.
+	attributes?: v1.Attributes @protobuf(1,type=Attributes)
+
+	//  HTTP request method to match against as defined by
+	//  [rfc7231](https://tools.ietf.org/html/rfc7231#page-21). For
+	//  example: GET, HEAD, POST, PUT, DELETE.
+	httpMethod?: string @protobuf(2,name=http_method)
+}
+HTTPAPISpecPattern: {
+	//  URI template to match against as defined by
+	//  [rfc6570](https://tools.ietf.org/html/rfc6570). For example, the
+	//  following are valid URI templates:
+	// 
+	//      /pets
+	//      /pets/{id}
+	//      /dictionary/{term:1}/{term}
+	//      /search{?q*,lang}
+	// 
+	uriTemplate: string @protobuf(3,name=uri_template)
+} | {
+	//  EXPERIMENTAL:
+	// 
+	//  ecmascript style regex-based match as defined by
+	//  [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). For
+	//  example,
+	// 
+	//      "^/pets/(.*?)?"
+	// 
+	regex: string @protobuf(4)
+}
+
+//  APIKey defines the explicit configuration for generating the
+//  `request.api_key` attribute from HTTP requests.
+// 
+//  See [API Keys](https://swagger.io/docs/specification/authentication/api-keys)
+//  for a general overview of API keys as defined by OpenAPI.
+APIKey: {
+}
+APIKey: {
+	//  API Key is sent as a query parameter. `query` represents the
+	//  query string parameter name.
+	// 
+	//  For example, `query=api_key` should be used with the
+	//  following request:
+	// 
+	//      GET /something?api_key=abcdef12345
+	// 
+	query: string @protobuf(1)
+} | {
+	//  API key is sent in a request header. `header` represents the
+	//  header name.
+	// 
+	//  For example, `header=X-API-KEY` should be used with the
+	//  following request:
+	// 
+	//      GET /something HTTP/1.1
+	//      X-API-Key: abcdef12345
+	// 
+	header: string @protobuf(2)
+} | {
+	//  API key is sent in a
+	//  [cookie](https://swagger.io/docs/specification/authentication/cookie-authentication),
+	// 
+	//  For example, `cookie=X-API-KEY` should be used for the
+	//  following request:
+	// 
+	//      GET /something HTTP/1.1
+	//      Cookie: X-API-KEY=abcdef12345
+	// 
+	cookie: string @protobuf(3)
+}
+
+//  HTTPAPISpecReference defines a reference to an HTTPAPISpec. This is
+//  typically used for establishing bindings between an HTTPAPISpec and an
+//  IstioService. For example, the following defines an
+//  HTTPAPISpecReference for service `foo` in namespace `bar`.
+// 
+//  ```yaml
+//  - name: foo
+//    namespace: bar
+//  ```
+HTTPAPISpecReference: {
+	//  REQUIRED. The short name of the HTTPAPISpec. This is the resource
+	//  name defined by the metadata name field.
+	name?: string @protobuf(1)
+
+	//  Optional namespace of the HTTPAPISpec. Defaults to the encompassing
+	//  HTTPAPISpecBinding's metadata namespace field.
+	namespace?: string @protobuf(2)
+}
+
+//  HTTPAPISpecBinding defines the binding between HTTPAPISpecs and one or more
+//  IstioService. For example, the following establishes a binding
+//  between the HTTPAPISpec `petstore` and service `foo` in namespace `bar`.
+// 
+//  ```yaml
+//  apiVersion: config.istio.io/v1alpha2
+//  kind: HTTPAPISpecBinding
+//  metadata:
+//    name: my-binding
+//    namespace: default
+//  spec:
+//    services:
+//    - name: foo
+//      namespace: bar
+//    api_specs:
+//    - name: petstore
+//      namespace: default
+//  ```
+HTTPAPISpecBinding: {
+	//  REQUIRED. One or more services to map the listed HTTPAPISpec onto.
+	services?: [...IstioService] @protobuf(1)
+
+	//  REQUIRED. One or more HTTPAPISpec references that should be mapped to
+	//  the specified service(s). The aggregate collection of match
+	//  conditions defined in the HTTPAPISpecs should not overlap.
+	apiSpecs?: [...HTTPAPISpecReference] @protobuf(2,name=api_specs)
+}
diff --git a/encoding/protobuf/testdata/mixer/v1/config/client/client_config.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config.proto
similarity index 100%
rename from encoding/protobuf/testdata/mixer/v1/config/client/client_config.proto
rename to encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue
new file mode 100644
index 0000000..2f4bf64
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/client_config_proto_gen.cue
@@ -0,0 +1,192 @@
+//  Copyright 2017 Istio Authors
+// 
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+// 
+//        http://www.apache.org/licenses/LICENSE-2.0
+// 
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+
+//  $title: Mixer Client
+//  $description: Configuration state for the Mixer client library.
+//  $location: https://istio.io/docs/reference/config/policy-and-telemetry/istio.mixer.v1.config.client
+
+//  Describes the configuration state for the Mixer client library that's built into Envoy.
+package client
+
+import (
+	"istio.io/api/mixer/v1"
+	"time"
+)
+
+//  Specifies the behavior when the client is unable to connect to Mixer.
+NetworkFailPolicy: {
+
+	//  Specifies the behavior when the client is unable to connect to Mixer.
+	policy?: NetworkFailPolicy_FailPolicy @protobuf(1,type=FailPolicy)
+
+	//  Max retries on transport error.
+	maxRetry?: uint32 @protobuf(2,name=max_retry)
+
+	//  Base time to wait between retries.  Will be adjusted by exponential
+	//  backoff and jitter.
+	baseRetryWait?: time.Duration @protobuf(3,type=google.protobuf.Duration,name=base_retry_wait)
+
+	//  Max time to wait between retries.
+	maxRetryWait?: time.Duration @protobuf(4,type=google.protobuf.Duration,name=max_retry_wait)
+}
+
+//  Describes the policy.
+NetworkFailPolicy_FailPolicy:
+	//  If network connection fails, request is allowed and delivered to the
+	//  service.
+	*"FAIL_OPEN" |
+
+	//  If network connection fails, request is rejected.
+	"FAIL_CLOSE"
+
+NetworkFailPolicy_FailPolicy_value: {
+	"FAIL_OPEN":  0
+	"FAIL_CLOSE": 1
+}
+
+//  Defines the per-service client configuration.
+ServiceConfig: {
+	//  If true, do not call Mixer Check.
+	disableCheckCalls?: bool @protobuf(1,name=disable_check_calls)
+
+	//  If true, do not call Mixer Report.
+	disableReportCalls?: bool @protobuf(2,name=disable_report_calls)
+
+	//  Send these attributes to Mixer in both Check and Report. This
+	//  typically includes the "destination.service" attribute.
+	//  In case of a per-route override, per-route attributes take precedence
+	//  over the attributes supplied in the client configuration.
+	mixerAttributes?: v1.Attributes @protobuf(3,type=Attributes,name=mixer_attributes)
+
+	//  HTTP API specifications to generate API attributes.
+	httpApiSpec?: [...HTTPAPISpec] @protobuf(4,name=http_api_spec)
+
+	//  Quota specifications to generate quota requirements.
+	quotaSpec?: [...QuotaSpec] @protobuf(5,name=quota_spec)
+
+	//  Specifies the behavior when the client is unable to connect to Mixer.
+	//  This is the service-level policy. It overrides
+	//  [mesh-level
+	//  policy][istio.mixer.v1.config.client.TransportConfig.network_fail_policy].
+	networkFailPolicy?: NetworkFailPolicy @protobuf(7,name=network_fail_policy)
+
+	//  Default attributes to forward to upstream. This typically
+	//  includes the "source.ip" and "source.uid" attributes.
+	//  In case of a per-route override, per-route attributes take precedence
+	//  over the attributes supplied in the client configuration.
+	// 
+	//  Forwarded attributes take precedence over the static Mixer attributes.
+	//  The full order of application is as follows:
+	//  1. static Mixer attributes from the filter config;
+	//  2. static Mixer attributes from the route config;
+	//  3. forwarded attributes from the source filter config (if any);
+	//  4. forwarded attributes from the source route config (if any);
+	//  5. derived attributes from the request metadata.
+	forwardAttributes?: v1.Attributes @protobuf(8,type=Attributes,name=forward_attributes)
+}
+
+//  Defines the transport config on how to call Mixer.
+TransportConfig: {
+	//  The flag to disable check cache.
+	disableCheckCache?: bool @protobuf(1,name=disable_check_cache)
+
+	//  The flag to disable quota cache.
+	disableQuotaCache?: bool @protobuf(2,name=disable_quota_cache)
+
+	//  The flag to disable report batch.
+	disableReportBatch?: bool @protobuf(3,name=disable_report_batch)
+
+	//  Specifies the behavior when the client is unable to connect to Mixer.
+	//  This is the mesh level policy. The default value for policy is FAIL_OPEN.
+	networkFailPolicy?: NetworkFailPolicy @protobuf(4,name=network_fail_policy)
+
+	//  Specify refresh interval to write Mixer client statistics to Envoy share
+	//  memory. If not specified, the interval is 10 seconds.
+	statsUpdateInterval?: time.Duration @protobuf(5,type=google.protobuf.Duration,name=stats_update_interval)
+
+	//  Name of the cluster that will forward check calls to a pool of mixer
+	//  servers. Defaults to "mixer_server". By using different names for
+	//  checkCluster and reportCluster, it is possible to have one set of
+	//  Mixer servers handle check calls, while another set of Mixer servers
+	//  handle report calls.
+	// 
+	//  NOTE: Any value other than the default "mixer_server" will require the
+	//  Istio Grafana dashboards to be reconfigured to use the new name.
+	checkCluster?: string @protobuf(6,name=check_cluster)
+
+	//  Name of the cluster that will forward report calls to a pool of mixer
+	//  servers. Defaults to "mixer_server". By using different names for
+	//  checkCluster and reportCluster, it is possible to have one set of
+	//  Mixer servers handle check calls, while another set of Mixer servers
+	//  handle report calls.
+	// 
+	//  NOTE: Any value other than the default "mixer_server" will require the
+	//  Istio Grafana dashboards to be reconfigured to use the new name.
+	reportCluster?: string @protobuf(7,name=report_cluster)
+
+	//  Default attributes to forward to Mixer upstream. This typically
+	//  includes the "source.ip" and "source.uid" attributes. These
+	//  attributes are consumed by the proxy in front of mixer.
+	attributesForMixerProxy?: v1.Attributes @protobuf(8,type=Attributes,name=attributes_for_mixer_proxy)
+}
+
+//  Defines the client config for HTTP.
+HttpClientConfig: {
+	//  The transport config.
+	transport?: TransportConfig @protobuf(1)
+
+	//  Map of control configuration indexed by destination.service. This
+	//  is used to support per-service configuration for cases where a
+	//  mixerclient serves multiple services.
+	serviceConfigs <_>: ServiceConfig
+
+	//  Default destination service name if none was specified in the
+	//  client request.
+	defaultDestinationService?: string @protobuf(3,name=default_destination_service)
+
+	//  Default attributes to send to Mixer in both Check and
+	//  Report. This typically includes "destination.ip" and
+	//  "destination.uid" attributes.
+	mixerAttributes?: v1.Attributes @protobuf(4,type=Attributes,name=mixer_attributes)
+
+	//  Default attributes to forward to upstream. This typically
+	//  includes the "source.ip" and "source.uid" attributes.
+	forwardAttributes?: v1.Attributes @protobuf(5,type=Attributes,name=forward_attributes)
+}
+
+//  Defines the client config for TCP.
+TcpClientConfig: {
+	//  The transport config.
+	transport?: TransportConfig @protobuf(1)
+
+	//  Default attributes to send to Mixer in both Check and
+	//  Report. This typically includes "destination.ip" and
+	//  "destination.uid" attributes.
+	mixerAttributes?: v1.Attributes @protobuf(2,type=Attributes,name=mixer_attributes)
+
+	//  If set to true, disables Mixer check calls.
+	disableCheckCalls?: bool @protobuf(3,name=disable_check_calls)
+
+	//  If set to true, disables Mixer check calls.
+	disableReportCalls?: bool @protobuf(4,name=disable_report_calls)
+
+	//  Quota specifications to generate quota requirements.
+	//  It applies on the new TCP connections.
+	connectionQuotaSpec?: QuotaSpec @protobuf(5,name=connection_quota_spec)
+
+	//  Specify report interval to send periodical reports for long TCP
+	//  connections. If not specified, the interval is 10 seconds. This interval
+	//  should not be less than 1 second, otherwise it will be reset to 1 second.
+	reportInterval?: time.Duration @protobuf(6,type=google.protobuf.Duration,name=report_interval)
+}
diff --git a/encoding/protobuf/testdata/mixer/v1/config/client/quota.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/quota.proto
similarity index 100%
rename from encoding/protobuf/testdata/mixer/v1/config/client/quota.proto
rename to encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/quota.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/quota_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/quota_proto_gen.cue
new file mode 100644
index 0000000..e5c97c8
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/quota_proto_gen.cue
@@ -0,0 +1,134 @@
+//  Copyright 2017 Istio Authors
+// 
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+// 
+//        http://www.apache.org/licenses/LICENSE-2.0
+// 
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+
+//  Specifies runtime quota rules.
+//   * Uses Istio attributes to match individual requests
+//   * Specifies list of quotas to use for matched requests.
+// 
+//  Example1:
+//  Charge "request_count" quota with 1 amount for all requests.
+// 
+//    QuotaSpec:
+//      - rules
+//        - quotas:
+//            quota: request_count
+//            charge: 1
+// 
+//  Example2:
+//  For HTTP POST requests with path are prefixed with /books or
+//  api.operation is create_books, charge two quotas:
+//  * write_count of 1 amount
+//  * request_count of 5 amount.
+// 
+//  ```yaml
+//  QuotaSpec:
+//    - rules:
+//      - match:
+//          clause:
+//            request.path:
+//              string_prefix: /books
+//            request.http_method:
+//              string_exact: POST
+//      - match:
+//          clause:
+//            api.operation:
+//              string_exact: create_books
+//      - quotas:
+//          quota: write_count
+//          charge: 1
+//      - quotas:
+//          quota: request_count
+//          charge: 5
+//  ```
+package client
+
+//  Determines the quotas used for individual requests.
+QuotaSpec: {
+	//  A list of Quota rules.
+	rules?: [...QuotaRule] @protobuf(1)
+}
+
+//  Specifies a rule with list of matches and list of quotas.
+//  If any clause matched, the list of quotas will be used.
+QuotaRule: {
+	//  If empty, match all request.
+	//  If any of match is true, it is matched.
+	match?: [...AttributeMatch] @protobuf(1)
+
+	//  The list of quotas to charge.
+	quotas?: [...Quota] @protobuf(2)
+}
+
+//  Describes how to match a given string in HTTP headers. Match is
+//  case-sensitive.
+StringMatch: {
+}
+StringMatch: {
+	//  exact string match
+	exact: string @protobuf(1)
+} | {
+	//  prefix-based match
+	prefix: string @protobuf(2)
+} | {
+	//  ECMAscript style regex-based match
+	regex: string @protobuf(3)
+}
+
+//  Specifies a match clause to match Istio attributes
+AttributeMatch: {
+	//  Map of attribute names to StringMatch type.
+	//  Each map element specifies one condition to match.
+	// 
+	//  Example:
+	// 
+	//    clause:
+	//      source.uid:
+	//        exact: SOURCE_UID
+	//      request.http_method:
+	//        exact: POST
+	clause <_>: StringMatch
+}
+
+//  Specifies a quota to use with quota name and amount.
+Quota: {
+	//  The quota name to charge
+	quota?: string @protobuf(1)
+
+	//  The quota amount to charge
+	charge?: int64 @protobuf(2)
+}
+
+//  QuotaSpecBinding defines the binding between QuotaSpecs and one or more
+//  IstioService.
+QuotaSpecBinding: {
+	//  REQUIRED. One or more services to map the listed QuotaSpec onto.
+	services?: [...IstioService] @protobuf(1)
+
+	//  REQUIRED. One or more QuotaSpec references that should be mapped to
+	//  the specified service(s). The aggregate collection of match
+	//  conditions defined in the QuotaSpecs should not overlap.
+	quotaSpecs?: [...QuotaSpecBinding_QuotaSpecReference] @protobuf(2,type=QuotaSpecReference,name=quota_specs)
+}
+
+//  QuotaSpecReference uniquely identifies the QuotaSpec used in the
+//  Binding.
+QuotaSpecBinding_QuotaSpecReference: {
+	//  REQUIRED. The short name of the QuotaSpec. This is the resource
+	//  name defined by the metadata name field.
+	name?: string @protobuf(1)
+
+	//  Optional namespace of the QuotaSpec. Defaults to the value of the
+	//  metadata namespace field.
+	namespace?: string @protobuf(2)
+}
diff --git a/encoding/protobuf/testdata/mixer/v1/config/client/service.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/service.proto
similarity index 100%
rename from encoding/protobuf/testdata/mixer/v1/config/client/service.proto
rename to encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/service.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/service_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/service_proto_gen.cue
new file mode 100644
index 0000000..9f97d90
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/config/client/service_proto_gen.cue
@@ -0,0 +1,46 @@
+//  Copyright 2017 Istio Authors
+// 
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+// 
+//        http://www.apache.org/licenses/LICENSE-2.0
+// 
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+
+//  NOTE: this is a duplicate of proxy.v1.config.IstioService from
+//  proxy/v1alpha1/config/route_rules.proto.
+// 
+//  Mixer protobufs have gogoproto specific options which are not
+//  compatiable with the proxy's vanilla protobufs. Ideally, these
+//  protobuf options be reconciled so fundamental Istio concepts and
+//  types can be shared by components. Until then, make a copy of
+//  IstioService for mixerclient to use.
+package client
+
+//  IstioService identifies a service and optionally service version.
+//  The FQDN of the service is composed from the name, namespace, and implementation-specific domain suffix
+//  (e.g. on Kubernetes, "reviews" + "default" + "svc.cluster.local" -> "reviews.default.svc.cluster.local").
+IstioService: {
+	//  The short name of the service such as "foo".
+	name?: string @protobuf(1)
+
+	//  Optional namespace of the service. Defaults to value of metadata namespace field.
+	namespace?: string @protobuf(2)
+
+	//  Domain suffix used to construct the service FQDN in implementations that support such specification.
+	domain?: string @protobuf(3)
+
+	//  The service FQDN.
+	service?: string @protobuf(4)
+
+	//  Optional one or more labels that uniquely identify the service version.
+	// 
+	//  *Note:* When used for a VirtualService destination, labels MUST be empty.
+	// 
+	labels <_>: string
+}
diff --git a/encoding/protobuf/testdata/mixer/v1/mixer.proto b/encoding/protobuf/testdata/istio.io/api/mixer/v1/mixer.proto
similarity index 100%
rename from encoding/protobuf/testdata/mixer/v1/mixer.proto
rename to encoding/protobuf/testdata/istio.io/api/mixer/v1/mixer.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/mixer/v1/mixer_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/mixer/v1/mixer_proto_gen.cue
new file mode 100644
index 0000000..9c4bf1c
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/mixer/v1/mixer_proto_gen.cue
@@ -0,0 +1,248 @@
+//  Copyright 2016 Istio Authors
+// 
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+// 
+//      http://www.apache.org/licenses/LICENSE-2.0
+// 
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+
+//  This package defines the Mixer API that the sidecar proxy uses to perform
+//  precondition checks, manage quotas, and report telemetry.
+package v1
+
+import (
+	"google.golang.org/genproto/googleapis/rpc/status"
+	"time"
+)
+
+//  Used to get a thumbs-up/thumbs-down before performing an action.
+CheckRequest: {
+
+	//  The attributes to use for this request.
+	// 
+	//  Mixer's configuration determines how these attributes are used to
+	//  establish the result returned in the response.
+	attributes?: CompressedAttributes @protobuf(1,"(gogoproto.nullable)=false")
+
+	//  The number of words in the global dictionary, used with to populate the attributes.
+	//  This value is used as a quick way to determine whether the client is using a dictionary that
+	//  the server understands.
+	globalWordCount?: uint32 @protobuf(2,name=global_word_count)
+
+	//  Used for deduplicating `Check` calls in the case of failed RPCs and retries. This should be a UUID
+	//  per call, where the same UUID is used for retries of the same call.
+	deduplicationId?: string @protobuf(3,name=deduplication_id)
+
+	//  The individual quotas to allocate
+	quotas <_>: CheckRequest_QuotaParams
+}
+
+//  parameters for a quota allocation
+CheckRequest_QuotaParams: {
+	//  Amount of quota to allocate
+	amount?: int64 @protobuf(1)
+
+	//  When true, supports returning less quota than what was requested.
+	bestEffort?: bool @protobuf(2,name=best_effort)
+}
+
+//  The response generated by the Check method.
+CheckResponse: {
+
+	//  The precondition check results.
+	precondition?: CheckResponse_PreconditionResult @protobuf(2,type=PreconditionResult,"(gogoproto.nullable)=false")
+
+	//  The resulting quota, one entry per requested quota.
+	quotas <_>: CheckResponse_QuotaResult
+}
+
+//  Expresses the result of a precondition check.
+CheckResponse_PreconditionResult: {
+
+	//  A status code of OK indicates all preconditions were satisfied. Any other code indicates not
+	//  all preconditions were satisfied and details describe why.
+	status?: __status.Status @protobuf(1,type=google.rpc.Status,"(gogoproto.nullable)=false")
+
+	//  The amount of time for which this result can be considered valid.
+	validDuration?: time.Duration @protobuf(2,type=google.protobuf.Duration,name=valid_duration,"(gogoproto.nullable)=false","(gogoproto.stdduration)")
+
+	//  The number of uses for which this result can be considered valid.
+	validUseCount?: int32 @protobuf(3,name=valid_use_count)
+
+	//  The total set of attributes that were used in producing the result
+	//  along with matching conditions.
+	referencedAttributes?: ReferencedAttributes @protobuf(5,name=referenced_attributes)
+
+	//  An optional routing directive, used to manipulate the traffic metadata
+	//  whenever all preconditions are satisfied.
+	routeDirective?: RouteDirective @protobuf(6,name=route_directive)
+}
+__status = status
+
+//  Expresses the result of a quota allocation.
+CheckResponse_QuotaResult: {
+	//  The amount of time for which this result can be considered valid.
+	validDuration?: time.Duration @protobuf(1,type=google.protobuf.Duration,name=valid_duration,"(gogoproto.nullable)=false","(gogoproto.stdduration)")
+
+	//  The amount of granted quota. When `QuotaParams.best_effort` is true, this will be >= 0.
+	//  If `QuotaParams.best_effort` is false, this will be either 0 or >= `QuotaParams.amount`.
+	grantedAmount?: int64 @protobuf(2,name=granted_amount)
+
+	//  The total set of attributes that were used in producing the result
+	//  along with matching conditions.
+	referencedAttributes?: ReferencedAttributes @protobuf(5,name=referenced_attributes,"(gogoproto.nullable)=false")
+}
+
+//  Describes the attributes that were used to determine the response.
+//  This can be used to construct a response cache.
+ReferencedAttributes: {
+
+	//  The message-level dictionary. Refer to [CompressedAttributes][istio.mixer.v1.CompressedAttributes] for information
+	//  on using dictionaries.
+	words?: [...string] @protobuf(1)
+
+	//  Describes a set of attributes.
+	attributeMatches?: [...ReferencedAttributes_AttributeMatch] @protobuf(2,type=AttributeMatch,name=attribute_matches,"(gogoproto.nullable)=false")
+}
+
+//  How an attribute's value was matched
+ReferencedAttributes_Condition:
+	*"CONDITION_UNSPECIFIED" | //  should not occur
+	"ABSENCE" | //  match when attribute doesn't exist
+	"EXACT" | //  match when attribute value is an exact byte-for-byte match
+	"REGEX" //  match when attribute value matches the included regex
+
+ReferencedAttributes_Condition_value: {
+	"CONDITION_UNSPECIFIED": 0
+	"ABSENCE":               1
+	"EXACT":                 2
+	"REGEX":                 3
+}
+
+//  Describes a single attribute match.
+ReferencedAttributes_AttributeMatch: {
+	//  The name of the attribute. This is a dictionary index encoded in a manner identical
+	//  to all strings in the [CompressedAttributes][istio.mixer.v1.CompressedAttributes] message.
+	name?: int32 @protobuf(1,type=sint32)
+
+	//  The kind of match against the attribute value.
+	condition?: ReferencedAttributes_Condition @protobuf(2,type=Condition)
+
+	//  If a REGEX condition is provided for a STRING_MAP attribute,
+	//  clients should use the regex value to match against map keys.
+	regex?: string @protobuf(3)
+
+	//  A key in a STRING_MAP. When multiple keys from a STRING_MAP
+	//  attribute were referenced, there will be multiple AttributeMatch
+	//  messages with different map_key values. Values for map_key SHOULD
+	//  be ignored for attributes that are not STRING_MAP.
+	// 
+	//  Indices for the keys are used (taken either from the
+	//  message dictionary from the `words` field or the global dictionary).
+	// 
+	//  If no map_key value is provided for a STRING_MAP attribute, the
+	//  entire STRING_MAP will be used.
+	mapKey?: int32 @protobuf(4,type=sint32,name=map_key)
+}
+
+//  Operation on HTTP headers to replace, append, or remove a header. Header
+//  names are normalized to lower-case with dashes, e.g.  "x-request-id".
+//  Pseudo-headers ":path", ":authority", and ":method" are supported to modify
+//  the request headers.
+HeaderOperation: {
+
+	//  Header name.
+	name?: string @protobuf(1)
+
+	//  Header value.
+	value?: string @protobuf(2)
+
+	//  Header operation.
+	operation?: HeaderOperation_Operation @protobuf(3,type=Operation)
+}
+
+//  Operation type.
+HeaderOperation_Operation:
+	*"REPLACE" | //  replaces the header with the given name
+	"REMOVE" | //  removes the header with the given name (the value is ignored)
+	"APPEND" //  appends the value to the header value, or sets it if not present
+
+HeaderOperation_Operation_value: {
+	"REPLACE": 0
+	"REMOVE":  1
+	"APPEND":  2
+}
+
+//  Expresses the routing manipulation actions to be performed on behalf of
+//  Mixer in response to a precondition check.
+RouteDirective: {
+	//  Operations on the request headers.
+	requestHeaderOperations?: [...HeaderOperation] @protobuf(1,name=request_header_operations,"(gogoproto.nullable)=false")
+
+	//  Operations on the response headers.
+	responseHeaderOperations?: [...HeaderOperation] @protobuf(2,name=response_header_operations,"(gogoproto.nullable)=false")
+
+	//  If set, enables a direct response without proxying the request to the routing
+	//  destination. Required to be a value in the 2xx or 3xx range.
+	directResponseCode?: uint32 @protobuf(3,name=direct_response_code)
+
+	//  Supplies the response body for the direct response.
+	//  If this setting is omitted, no body is included in the generated response.
+	directResponseBody?: string @protobuf(4,name=direct_response_body)
+}
+
+//  Used to report telemetry after performing one or more actions.
+ReportRequest: {
+
+	//  next value: 5
+
+	//  The attributes to use for this request.
+	// 
+	//  Each `Attributes` element represents the state of a single action. Multiple actions
+	//  can be provided in a single message in order to improve communication efficiency. The
+	//  client can accumulate a set of actions and send them all in one single message.
+	attributes?: [...CompressedAttributes] @protobuf(1,"(gogoproto.nullable)=false")
+
+	//  Indicates how to decode the attributes sets in this request.
+	repeatedAttributesSemantics?: ReportRequest_RepeatedAttributesSemantics @protobuf(4,type=RepeatedAttributesSemantics,name=repeated_attributes_semantics)
+
+	//  The default message-level dictionary for all the attributes.
+	//  Individual attribute messages can have their own dictionaries, but if they don't
+	//  then this set of words, if it is provided, is used instead.
+	// 
+	//  This makes it possible to share the same dictionary for all attributes in this
+	//  request, which can substantially reduce the overall request size.
+	defaultWords?: [...string] @protobuf(2,name=default_words)
+
+	//  The number of words in the global dictionary.
+	//  To detect global dictionary out of sync between client and server.
+	globalWordCount?: uint32 @protobuf(3,name=global_word_count)
+}
+
+//  Used to signal how the sets of compressed attributes should be reconstitued server-side.
+ReportRequest_RepeatedAttributesSemantics:
+	//  Use delta encoding between sets of compressed attributes to reduce the overall on-wire
+	//  request size. Each individual set of attributes is used to modify the previous set.
+	//  NOTE: There is no way with this encoding to specify attribute value deletion. This 
+	//  option should be used with extreme caution.
+	*"DELTA_ENCODING" |
+
+	//  Treat each set of compressed attributes as complete - independent from other sets
+	//  in this request. This will result in on-wire duplication of attributes and values, but
+	//  will allow for proper accounting of absent values in overall encoding.
+	"INDEPENDENT_ENCODING"
+
+ReportRequest_RepeatedAttributesSemantics_value: {
+	"DELTA_ENCODING":       0
+	"INDEPENDENT_ENCODING": 1
+}
+
+//  Used to carry responses to telemetry reports
+ReportResponse: {
+}
diff --git a/encoding/protobuf/testdata/networking/v1alpha3/gateway.proto b/encoding/protobuf/testdata/istio.io/api/networking/v1alpha3/gateway.proto
similarity index 100%
rename from encoding/protobuf/testdata/networking/v1alpha3/gateway.proto
rename to encoding/protobuf/testdata/istio.io/api/networking/v1alpha3/gateway.proto
diff --git a/encoding/protobuf/testdata/istio.io/api/networking/v1alpha3/gateway_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/networking/v1alpha3/gateway_proto_gen.cue
new file mode 100644
index 0000000..5356909
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/networking/v1alpha3/gateway_proto_gen.cue
@@ -0,0 +1,450 @@
+//  Copyright 2019 CUE Authors
+// 
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+//  
+//      http://www.apache.org/licenses/LICENSE-2.0
+//  
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+
+//  Copyright 2017 Istio Authors
+// 
+//    Licensed under the Apache License, Version 2.0 (the "License");
+//    you may not use this file except in compliance with the License.
+//    You may obtain a copy of the License at
+// 
+//        http://www.apache.org/licenses/LICENSE-2.0
+// 
+//    Unless required by applicable law or agreed to in writing, software
+//    distributed under the License is distributed on an "AS IS" BASIS,
+//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//    See the License for the specific language governing permissions and
+//    limitations under the License.
+
+//  $title: Gateway
+//  $description: Configuration affecting edge load balancer.
+//  $location: https://istio.io/docs/reference/config/networking/v1alpha3/gateway.html
+
+//  `Gateway` describes a load balancer operating at the edge of the mesh
+//  receiving incoming or outgoing HTTP/TCP connections. The specification
+//  describes a set of ports that should be exposed, the type of protocol to
+//  use, SNI configuration for the load balancer, etc.
+// 
+//  For example, the following Gateway configuration sets up a proxy to act
+//  as a load balancer exposing port 80 and 9080 (http), 443 (https),
+//  9443(https) and port 2379 (TCP) for ingress.  The gateway will be
+//  applied to the proxy running on a pod with labels `app:
+//  my-gateway-controller`. While Istio will configure the proxy to listen
+//  on these ports, it is the responsibility of the user to ensure that
+//  external traffic to these ports are allowed into the mesh.
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: Gateway
+//  metadata:
+//    name: my-gateway
+//    namespace: some-config-namespace
+//  spec:
+//    selector:
+//      app: my-gateway-controller
+//    servers:
+//    - port:
+//        number: 80
+//        name: http
+//        protocol: HTTP
+//      hosts:
+//      - uk.bookinfo.com
+//      - eu.bookinfo.com
+//      tls:
+//        httpsRedirect: true # sends 301 redirect for http requests
+//    - port:
+//        number: 443
+//        name: https-443
+//        protocol: HTTPS
+//      hosts:
+//      - uk.bookinfo.com
+//      - eu.bookinfo.com
+//      tls:
+//        mode: SIMPLE # enables HTTPS on this port
+//        serverCertificate: /etc/certs/servercert.pem
+//        privateKey: /etc/certs/privatekey.pem
+//    - port:
+//        number: 9443
+//        name: https-9443
+//        protocol: HTTPS
+//      hosts:
+//      - "bookinfo-namespace/*.bookinfo.com"
+//      tls:
+//        mode: SIMPLE # enables HTTPS on this port
+//        credentialName: bookinfo-secret # fetches certs from Kubernetes secret
+//    - port:
+//        number: 9080
+//        name: http-wildcard
+//        protocol: HTTP
+//      hosts:
+//      - "*"
+//    - port:
+//        number: 2379 # to expose internal service via external port 2379
+//        name: mongo
+//        protocol: MONGO
+//      hosts:
+//      - "*"
+//  ```
+// 
+//  The Gateway specification above describes the L4-L6 properties of a load
+//  balancer. A `VirtualService` can then be bound to a gateway to control
+//  the forwarding of traffic arriving at a particular host or gateway port.
+// 
+//  For example, the following VirtualService splits traffic for
+//  `https://uk.bookinfo.com/reviews`, `https://eu.bookinfo.com/reviews`,
+//  `http://uk.bookinfo.com:9080/reviews`,
+//  `http://eu.bookinfo.com:9080/reviews` into two versions (prod and qa) of
+//  an internal reviews service on port 9080. In addition, requests
+//  containing the cookie "user: dev-123" will be sent to special port 7777
+//  in the qa version. The same rule is also applicable inside the mesh for
+//  requests to the "reviews.prod.svc.cluster.local" service. This rule is
+//  applicable across ports 443, 9080. Note that `http://uk.bookinfo.com`
+//  gets redirected to `https://uk.bookinfo.com` (i.e. 80 redirects to 443).
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: VirtualService
+//  metadata:
+//    name: bookinfo-rule
+//    namespace: bookinfo-namespace
+//  spec:
+//    hosts:
+//    - reviews.prod.svc.cluster.local
+//    - uk.bookinfo.com
+//    - eu.bookinfo.com
+//    gateways:
+//    - some-config-namespace/my-gateway
+//    - mesh # applies to all the sidecars in the mesh
+//    http:
+//    - match:
+//      - headers:
+//          cookie:
+//            exact: "user=dev-123"
+//      route:
+//      - destination:
+//          port:
+//            number: 7777
+//          host: reviews.qa.svc.cluster.local
+//    - match:
+//      - uri:
+//          prefix: /reviews/
+//      route:
+//      - destination:
+//          port:
+//            number: 9080 # can be omitted if it's the only port for reviews
+//          host: reviews.prod.svc.cluster.local
+//        weight: 80
+//      - destination:
+//          host: reviews.qa.svc.cluster.local
+//        weight: 20
+//  ```
+// 
+//  The following VirtualService forwards traffic arriving at (external)
+//  port 27017 to internal Mongo server on port 5555. This rule is not
+//  applicable internally in the mesh as the gateway list omits the
+//  reserved name `mesh`.
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: VirtualService
+//  metadata:
+//    name: bookinfo-Mongo
+//    namespace: bookinfo-namespace
+//  spec:
+//    hosts:
+//    - mongosvr.prod.svc.cluster.local # name of internal Mongo service
+//    gateways:
+//    - some-config-namespace/my-gateway # can omit the namespace if gateway is in same
+//                                         namespace as virtual service.
+//    tcp:
+//    - match:
+//      - port: 27017
+//      route:
+//      - destination:
+//          host: mongo.prod.svc.cluster.local
+//          port:
+//            number: 5555
+//  ```
+// 
+//  It is possible to restrict the set of virtual services that can bind to
+//  a gateway server using the namespace/hostname syntax in the hosts field.
+//  For example, the following Gateway allows any virtual service in the ns1
+//  namespace to bind to it, while restricting only the virtual service with
+//  foo.bar.com host in the ns2 namespace to bind to it.
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: Gateway
+//  metadata:
+//    name: my-gateway
+//    namespace: some-config-namespace
+//  spec:
+//    selector:
+//      app: my-gateway-controller
+//    servers:
+//    - port:
+//        number: 80
+//        name: http
+//        protocol: HTTP
+//      hosts:
+//      - "ns1/*"
+//      - "ns2/foo.bar.com"
+//  ```
+// 
+package v1alpha3
+
+Gateway: {
+	//  REQUIRED: A list of server specifications.
+	servers?: [...Server] @protobuf(1)
+
+	//  REQUIRED: One or more labels that indicate a specific set of pods/VMs
+	//  on which this gateway configuration should be applied. The scope of
+	//  label search is restricted to the configuration namespace in which the
+	//  the resource is present. In other words, the Gateway resource must
+	//  reside in the same namespace as the gateway workload instance.
+	selector <_>: string
+	selector?: {<name>: name}
+}
+
+//  `Server` describes the properties of the proxy on a given load balancer
+//  port. For example,
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: Gateway
+//  metadata:
+//    name: my-ingress
+//  spec:
+//    selector:
+//      app: my-ingress-gateway
+//    servers:
+//    - port:
+//        number: 80
+//        name: http2
+//        protocol: HTTP2
+//      hosts:
+//      - "*"
+//  ```
+// 
+//  Another example
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: Gateway
+//  metadata:
+//    name: my-tcp-ingress
+//  spec:
+//    selector:
+//      app: my-tcp-ingress-gateway
+//    servers:
+//    - port:
+//        number: 27018
+//        name: mongo
+//        protocol: MONGO
+//      hosts:
+//      - "*"
+//  ```
+// 
+//  The following is an example of TLS configuration for port 443
+// 
+//  ```yaml
+//  apiVersion: networking.istio.io/v1alpha3
+//  kind: Gateway
+//  metadata:
+//    name: my-tls-ingress
+//  spec:
+//    selector:
+//      app: my-tls-ingress-gateway
+//    servers:
+//    - port:
+//        number: 443
+//        name: https
+//        protocol: HTTPS
+//      hosts:
+//      - "*"
+//      tls:
+//        mode: SIMPLE
+//        serverCertificate: /etc/certs/server.pem
+//        privateKey: /etc/certs/privatekey.pem
+//  ```
+Server: {
+	//  REQUIRED: The Port on which the proxy should listen for incoming
+	//  connections.
+	port?: Port @protobuf(1)
+	port?: >10 & <100
+
+	//  $hide_from_docs
+	//  The ip or the Unix domain socket to which the listener should be bound
+	//  to. Format: `x.x.x.x` or `unix:///path/to/uds` or `unix://@foobar`
+	//  (Linux abstract namespace). When using Unix domain sockets, the port
+	//  number should be 0.
+	bind?: string @protobuf(4)
+
+	//  REQUIRED. One or more hosts exposed by this gateway.
+	//  While typically applicable to
+	//  HTTP services, it can also be used for TCP services using TLS with SNI.
+	//  A host is specified as a `dnsName` with an optional `namespace/` prefix.
+	//  The `dnsName` should be specified using FQDN format, optionally including
+	//  a wildcard character in the left-most component (e.g., `prod/*.example.com`).
+	//  Set the `dnsName` to `*` to select all `VirtualService` hosts from the
+	//  specified namespace (e.g.,`prod/*`). If no `namespace/` is specified,
+	//  the `VirtualService` hosts will be selected from any available namespace.
+	//  Any associated `DestinationRule` in the same namespace will also be used.
+	// 
+	//  A `VirtualService` must be bound to the gateway and must have one or
+	//  more hosts that match the hosts specified in a server. The match
+	//  could be an exact match or a suffix match with the server's hosts. For
+	//  example, if the server's hosts specifies `*.example.com`, a
+	//  `VirtualService` with hosts `dev.example.com` or `prod.example.com` will
+	//  match. However, a `VirtualService` with host `example.com` or
+	//  `newexample.com` will not match.
+	// 
+	//  NOTE: Only virtual services exported to the gateway's namespace
+	//  (e.g., `exportTo` value of `*`) can be referenced.
+	//  Private configurations (e.g., `exportTo` set to `.`) will not be
+	//  available. Refer to the `exportTo` setting in `VirtualService`,
+	//  `DestinationRule`, and `ServiceEntry` configurations for details.
+	hosts?: [...string] @protobuf(2)
+
+	//  Set of TLS related options that govern the server's behavior. Use
+	//  these options to control if all http requests should be redirected to
+	//  https, and the TLS modes to use.
+	tls?: Server_TLSOptions @protobuf(3,type=TLSOptions)
+
+	//  The loopback IP endpoint or Unix domain socket to which traffic should
+	//  be forwarded to by default. Format should be `127.0.0.1:PORT` or
+	//  `unix:///path/to/socket` or `unix://@foobar` (Linux abstract namespace).
+	defaultEndpoint?: string @protobuf(5,name=default_endpoint)
+}
+
+Server_TLSOptions: {
+	//  If set to true, the load balancer will send a 301 redirect for all
+	//  http connections, asking the clients to use HTTPS.
+	httpsRedirect?: bool @protobuf(1,name=https_redirect)
+
+	//  Optional: Indicates whether connections to this port should be
+	//  secured using TLS. The value of this field determines how TLS is
+	//  enforced.
+	mode?: Server_TLSOptions_TLSmode @protobuf(2,type=TLSmode)
+
+	//  Extra comment.
+
+	//  REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
+	//  holding the server-side TLS certificate to use.
+	serverCertificate?: string @protobuf(3,name=server_certificate)
+
+	//  REQUIRED if mode is `SIMPLE` or `MUTUAL`. The path to the file
+	//  holding the server's private key.
+	privateKey?: string @protobuf(4,name=private_key)
+
+	//  REQUIRED if mode is `MUTUAL`. The path to a file containing
+	//  certificate authority certificates to use in verifying a presented
+	//  client side certificate.
+	caCertificates?: string @protobuf(5,name=ca_certificates)
+
+	//  The credentialName stands for a unique identifier that can be used
+	//  to identify the serverCertificate and the privateKey. The
+	//  credentialName appended with suffix "-cacert" is used to identify
+	//  the CaCertificates associated with this server. Gateway workloads
+	//  capable of fetching credentials from a remote credential store such
+	//  as Kubernetes secrets, will be configured to retrieve the
+	//  serverCertificate and the privateKey using credentialName, instead
+	//  of using the file system paths specified above. If using mutual TLS,
+	//  gateway workload instances will retrieve the CaCertificates using
+	//  credentialName-cacert. The semantics of the name are platform
+	//  dependent.  In Kubernetes, the default Istio supplied credential
+	//  server expects the credentialName to match the name of the
+	//  Kubernetes secret that holds the server certificate, the private
+	//  key, and the CA certificate (if using mutual TLS). Set the
+	//  `ISTIO_META_USER_SDS` metadata variable in the gateway's proxy to
+	//  enable the dynamic credential fetching feature.
+	credentialName?: string @protobuf(10,name=credential_name)
+
+	//  A list of alternate names to verify the subject identity in the
+	//  certificate presented by the client.
+	subjectAltNames?: [...string] @protobuf(6,name=subject_alt_names)
+
+	//  Optional: Minimum TLS protocol version.
+	minProtocolVersion?: Server_TLSOptions_TLSProtocol @protobuf(7,type=TLSProtocol,name=min_protocol_version)
+
+	//  Optional: Maximum TLS protocol version.
+	maxProtocolVersion?: Server_TLSOptions_TLSProtocol @protobuf(8,type=TLSProtocol,name=max_protocol_version)
+
+	//  Optional: If specified, only support the specified cipher list.
+	//  Otherwise default to the default cipher list supported by Envoy.
+	cipherSuites?: [...string] @protobuf(9,name=cipher_suites)
+}
+
+//  TLS modes enforced by the proxy
+Server_TLSOptions_TLSmode:
+	//  The SNI string presented by the client will be used as the match
+	//  criterion in a VirtualService TLS route to determine the
+	//  destination service from the service registry.
+	*"PASSTHROUGH" |
+
+	//  Secure connections with standard TLS semantics.
+	"SIMPLE" |
+
+	//  Secure connections to the upstream using mutual TLS by presenting
+	//  client certificates for authentication.
+	"MUTUAL" |
+
+	//  Similar to the passthrough mode, except servers with this TLS mode
+	//  do not require an associated VirtualService to map from the SNI
+	//  value to service in the registry. The destination details such as
+	//  the service/subset/port are encoded in the SNI value. The proxy
+	//  will forward to the upstream (Envoy) cluster (a group of
+	//  endpoints) specified by the SNI value. This server is typically
+	//  used to provide connectivity between services in disparate L3
+	//  networks that otherwise do not have direct connectivity between
+	//  their respective endpoints. Use of this mode assumes that both the
+	//  source and the destination are using Istio mTLS to secure traffic.
+	"AUTO_PASSTHROUGH"
+
+Server_TLSOptions_TLSmode_value: {
+	"PASSTHROUGH":      0
+	"SIMPLE":           1
+	"MUTUAL":           2
+	"AUTO_PASSTHROUGH": 3
+}
+
+//  TLS protocol versions.
+Server_TLSOptions_TLSProtocol:
+	*"TLS_AUTO" | //  Automatically choose the optimal TLS version.
+	"TLSV1_0" | //  TLS version 1.0
+	"TLSV1_1" | //  TLS version 1.1
+	"TLSV1_2" | //  TLS version 1.2
+	"TLSV1_3" //  TLS version 1.3
+
+Server_TLSOptions_TLSProtocol_value: {
+	"TLS_AUTO": 0
+	"TLSV1_0":  1
+	"TLSV1_1":  2
+	"TLSV1_2":  3
+	"TLSV1_3":  4
+}
+
+//  Port describes the properties of a specific port of a service.
+Port: {
+	//  REQUIRED: A valid non-negative integer port number.
+	number?: uint32 @protobuf(1)
+
+	//  REQUIRED: The protocol exposed on the port.
+	//  MUST BE one of HTTP|HTTPS|GRPC|HTTP2|MONGO|TCP|TLS.
+	//  TLS implies the connection will be routed based on the SNI header to
+	//  the destination without terminating the TLS connection.
+	protocol?: string @protobuf(2)
+
+	//  Label assigned to the port.
+	name?: string @protobuf(3)
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/github.com/gogo/protobuf/gogoproto/gogo_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/gogo/protobuf/gogoproto/gogo_proto_gen.cue
new file mode 100644
index 0000000..044eabf
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/gogo/protobuf/gogoproto/gogo_proto_gen.cue
@@ -0,0 +1,29 @@
+
+//  Protocol Buffers for Go with Gadgets
+// 
+//  Copyright (c) 2013, The GoGo Authors. All rights reserved.
+//  http://github.com/gogo/protobuf
+// 
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions are
+//  met:
+// 
+//      * Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//      * Redistributions in binary form must reproduce the above
+//  copyright notice, this list of conditions and the following disclaimer
+//  in the documentation and/or other materials provided with the
+//  distribution.
+// 
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+package gogoproto
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor_proto_gen.cue
new file mode 100644
index 0000000..7ceb8fc
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/protoc-gen-go/descriptor/descriptor_proto_gen.cue
@@ -0,0 +1,860 @@
+//  Protocol Buffers - Google's data interchange format
+//  Copyright 2008 Google Inc.  All rights reserved.
+//  https://developers.google.com/protocol-buffers/
+// 
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions are
+//  met:
+// 
+//      * Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//      * Redistributions in binary form must reproduce the above
+//  copyright notice, this list of conditions and the following disclaimer
+//  in the documentation and/or other materials provided with the
+//  distribution.
+//      * Neither the name of Google Inc. nor the names of its
+//  contributors may be used to endorse or promote products derived from
+//  this software without specific prior written permission.
+// 
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+//  Author: kenton@google.com (Kenton Varda)
+//   Based on original Protocol Buffers design by
+//   Sanjay Ghemawat, Jeff Dean, and others.
+// 
+//  The messages in this file describe the definitions found in .proto files.
+//  A valid .proto file can be translated directly to a FileDescriptorProto
+//  without any other information (e.g. without reading its imports).
+
+//  ===================================================================
+//  Options
+
+//  Each of the definitions above may have "options" attached.  These are
+//  just annotations which may cause code to be generated slightly differently
+//  or may contain hints for code that manipulates protocol messages.
+// 
+//  Clients may define custom options as extensions of the *Options messages.
+//  These extensions may not yet be known at parsing time, so the parser cannot
+//  store the values in them.  Instead it stores them in a field in the *Options
+//  message called uninterpreted_option. This field must have the same name
+//  across all *Options messages. We then use this field to populate the
+//  extensions when we build a descriptor, at which point all protos have been
+//  parsed and so all extensions are known.
+// 
+//  Extension numbers for custom options may be chosen as follows:
+//  * For options which will only be used within a single application or
+//    organization, or for experimental options, use field numbers 50000
+//    through 99999.  It is up to you to ensure that you do not use the
+//    same number for multiple options.
+//  * For options which will be published and used publicly by multiple
+//    independent entities, e-mail protobuf-global-extension-registry@google.com
+//    to reserve extension numbers. Simply provide your project name (e.g.
+//    Objective-C plugin) and your project website (if available) -- there's no
+//    need to explain how you intend to use them. Usually you only need one
+//    extension number. You can declare multiple options with only one extension
+//    number by putting them in a sub-message. See the Custom Options section of
+//    the docs for examples:
+//    https://developers.google.com/protocol-buffers/docs/proto#options
+//    If this turns out to be popular, a web service will be set up
+//    to automatically assign option numbers.
+
+//  ===================================================================
+//  Optional source code info
+package descriptor
+
+//  The protocol compiler can output a FileDescriptorSet containing the .proto
+//  files it parses.
+FileDescriptorSet: {
+	file?: [...FileDescriptorProto] @protobuf(1)
+}
+
+//  Describes a complete .proto file.
+FileDescriptorProto: {
+	name?:    string @protobuf(1) //  file name, relative to root of source tree
+	package?: string @protobuf(2) //  e.g. "foo", "foo.bar", etc.
+
+	//  Names of files imported by this file.
+	dependency?: [...string] @protobuf(3)
+
+	//  Indexes of the public imported files in the dependency list above.
+	publicDependency?: [...int32] @protobuf(10,name=public_dependency)
+
+	//  Indexes of the weak imported files in the dependency list.
+	//  For Google-internal migration only. Do not use.
+	weakDependency?: [...int32] @protobuf(11,name=weak_dependency)
+
+	//  All top-level definitions in this file.
+	messageType?: [...DescriptorProto] @protobuf(4,name=message_type)
+	enumType?: [...EnumDescriptorProto] @protobuf(5,name=enum_type)
+	service?: [...ServiceDescriptorProto] @protobuf(6)
+	extension?: [...FieldDescriptorProto] @protobuf(7)
+	options?: FileOptions @protobuf(8)
+
+	//  This field contains optional information about the original source code.
+	//  You may safely remove this entire field without harming runtime
+	//  functionality of the descriptors -- the information is needed only by
+	//  development tools.
+	sourceCodeInfo?: SourceCodeInfo @protobuf(9,name=source_code_info)
+
+	//  The syntax of the proto file.
+	//  The supported values are "proto2" and "proto3".
+	syntax?: string @protobuf(12)
+}
+
+//  Describes a message type.
+DescriptorProto: {
+	name?: string @protobuf(1)
+	field?: [...FieldDescriptorProto] @protobuf(2)
+	extension?: [...FieldDescriptorProto] @protobuf(6)
+	nestedType?: [...DescriptorProto] @protobuf(3,name=nested_type)
+	enumType?: [...EnumDescriptorProto] @protobuf(4,name=enum_type)
+	extensionRange?: [...DescriptorProto_ExtensionRange] @protobuf(5,type=ExtensionRange,name=extension_range)
+	oneofDecl?: [...OneofDescriptorProto] @protobuf(8,name=oneof_decl)
+	options?: MessageOptions @protobuf(7)
+	reservedRange?: [...DescriptorProto_ReservedRange] @protobuf(9,type=ReservedRange,name=reserved_range)
+
+	//  Reserved field names, which may not be used by fields in the same message.
+	//  A given name may only be reserved once.
+	reservedName?: [...string] @protobuf(10,name=reserved_name)
+}
+
+DescriptorProto_ExtensionRange: {
+	start?:   int32                 @protobuf(1) //  Inclusive.
+	end?:     int32                 @protobuf(2) //  Exclusive.
+	options?: ExtensionRangeOptions @protobuf(3)
+}
+
+//  Range of reserved tag numbers. Reserved tag numbers may not be used by
+//  fields or extension ranges in the same message. Reserved ranges may
+//  not overlap.
+DescriptorProto_ReservedRange: {
+	start?: int32 @protobuf(1) //  Inclusive.
+	end?:   int32 @protobuf(2) //  Exclusive.
+}
+
+ExtensionRangeOptions: {
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+//  Describes a field within a message.
+FieldDescriptorProto: {
+	name?:   string                     @protobuf(1)
+	number?: int32                      @protobuf(3)
+	label?:  FieldDescriptorProto_Label @protobuf(4,type=Label)
+
+	//  If type_name is set, this need not be set.  If both this and type_name
+	//  are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+	type?: FieldDescriptorProto_Type @protobuf(5,type=Type)
+
+	//  For message and enum types, this is the name of the type.  If the name
+	//  starts with a '.', it is fully-qualified.  Otherwise, C++-like scoping
+	//  rules are used to find the type (i.e. first the nested types within this
+	//  message are searched, then within the parent, on up to the root
+	//  namespace).
+	typeName?: string @protobuf(6,name=type_name)
+
+	//  For extensions, this is the name of the type being extended.  It is
+	//  resolved in the same manner as type_name.
+	extendee?: string @protobuf(2)
+
+	//  For numeric types, contains the original text representation of the value.
+	//  For booleans, "true" or "false".
+	//  For strings, contains the default text contents (not escaped in any way).
+	//  For bytes, contains the C escaped value.  All bytes >= 128 are escaped.
+	//  TODO(kenton):  Base-64 encode?
+	defaultValue?: string @protobuf(7,name=default_value)
+
+	//  If set, gives the index of a oneof in the containing type's oneof_decl
+	//  list.  This field is a member of that oneof.
+	oneofIndex?: int32 @protobuf(9,name=oneof_index)
+
+	//  JSON name of this field. The value is set by protocol compiler. If the
+	//  user has set a "json_name" option on this field, that option's value
+	//  will be used. Otherwise, it's deduced from the field's name by converting
+	//  it to camelCase.
+	jsonName?: string       @protobuf(10,name=json_name)
+	options?:  FieldOptions @protobuf(8)
+}
+FieldDescriptorProto_Type:
+	//  0 is reserved for errors.
+	//  Order is weird for historical reasons.
+	*"TYPE_DOUBLE" |
+	"TYPE_FLOAT" |
+
+	//  Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT64 if
+	//  negative values are likely.
+	"TYPE_INT64" |
+	"TYPE_UINT64" |
+
+	//  Not ZigZag encoded.  Negative numbers take 10 bytes.  Use TYPE_SINT32 if
+	//  negative values are likely.
+	"TYPE_INT32" |
+	"TYPE_FIXED64" |
+	"TYPE_FIXED32" |
+	"TYPE_BOOL" |
+	"TYPE_STRING" |
+
+	//  Tag-delimited aggregate.
+	//  Group type is deprecated and not supported in proto3. However, Proto3
+	//  implementations should still be able to parse the group wire format and
+	//  treat group fields as unknown fields.
+	"TYPE_GROUP" |
+	"TYPE_MESSAGE" | //  Length-delimited aggregate.
+
+	//  New in version 2.
+	"TYPE_BYTES" |
+	"TYPE_UINT32" |
+	"TYPE_ENUM" |
+	"TYPE_SFIXED32" |
+	"TYPE_SFIXED64" |
+	"TYPE_SINT32" | //  Uses ZigZag encoding.
+	"TYPE_SINT64" //  Uses ZigZag encoding.
+
+FieldDescriptorProto_Type_value: {
+	"TYPE_DOUBLE":   1
+	"TYPE_FLOAT":    2
+	"TYPE_INT64":    3
+	"TYPE_UINT64":   4
+	"TYPE_INT32":    5
+	"TYPE_FIXED64":  6
+	"TYPE_FIXED32":  7
+	"TYPE_BOOL":     8
+	"TYPE_STRING":   9
+	"TYPE_GROUP":    10
+	"TYPE_MESSAGE":  11
+	"TYPE_BYTES":    12
+	"TYPE_UINT32":   13
+	"TYPE_ENUM":     14
+	"TYPE_SFIXED32": 15
+	"TYPE_SFIXED64": 16
+	"TYPE_SINT32":   17
+	"TYPE_SINT64":   18
+}
+FieldDescriptorProto_Label:
+	//  0 is reserved for errors
+	*"LABEL_OPTIONAL" |
+	"LABEL_REQUIRED" |
+	"LABEL_REPEATED"
+
+FieldDescriptorProto_Label_value: {
+	"LABEL_OPTIONAL": 1
+	"LABEL_REQUIRED": 2
+	"LABEL_REPEATED": 3
+}
+
+//  Describes a oneof.
+OneofDescriptorProto: {
+	name?:    string       @protobuf(1)
+	options?: OneofOptions @protobuf(2)
+}
+
+//  Describes an enum type.
+EnumDescriptorProto: {
+	name?: string @protobuf(1)
+	value?: [...EnumValueDescriptorProto] @protobuf(2)
+	options?: EnumOptions @protobuf(3)
+
+	//  Range of reserved numeric values. Reserved numeric values may not be used
+	//  by enum values in the same enum declaration. Reserved ranges may not
+	//  overlap.
+	reservedRange?: [...EnumDescriptorProto_EnumReservedRange] @protobuf(4,type=EnumReservedRange,name=reserved_range)
+
+	//  Reserved enum value names, which may not be reused. A given name may only
+	//  be reserved once.
+	reservedName?: [...string] @protobuf(5,name=reserved_name)
+}
+
+//  Range of reserved numeric values. Reserved values may not be used by
+//  entries in the same enum. Reserved ranges may not overlap.
+// 
+//  Note that this is distinct from DescriptorProto.ReservedRange in that it
+//  is inclusive such that it can appropriately represent the entire int32
+//  domain.
+EnumDescriptorProto_EnumReservedRange: {
+	start?: int32 @protobuf(1) //  Inclusive.
+	end?:   int32 @protobuf(2) //  Inclusive.
+}
+
+//  Describes a value within an enum.
+EnumValueDescriptorProto: {
+	name?:    string           @protobuf(1)
+	number?:  int32            @protobuf(2)
+	options?: EnumValueOptions @protobuf(3)
+}
+
+//  Describes a service.
+ServiceDescriptorProto: {
+	name?: string @protobuf(1)
+	method?: [...MethodDescriptorProto] @protobuf(2)
+	options?: ServiceOptions @protobuf(3)
+}
+
+//  Describes a method of a service.
+MethodDescriptorProto: {
+	name?: string @protobuf(1)
+
+	//  Input and output type names.  These are resolved in the same way as
+	//  FieldDescriptorProto.type_name, but must refer to a message type.
+	inputType?:  string        @protobuf(2,name=input_type)
+	outputType?: string        @protobuf(3,name=output_type)
+	options?:    MethodOptions @protobuf(4)
+
+	//  Identifies if client streams multiple client messages
+	clientStreaming?: bool @protobuf(5,name=client_streaming,"default=false")
+
+	//  Identifies if server streams multiple server messages
+	serverStreaming?: bool @protobuf(6,name=server_streaming,"default=false")
+}
+
+FileOptions: {
+	//  Sets the Java package where classes generated from this .proto will be
+	//  placed.  By default, the proto package is used, but this is often
+	//  inappropriate because proto packages do not normally start with backwards
+	//  domain names.
+	javaPackage?: string @protobuf(1,name=java_package)
+
+	//  If set, all the classes from the .proto file are wrapped in a single
+	//  outer class with the given name.  This applies to both Proto1
+	//  (equivalent to the old "--one_java_file" option) and Proto2 (where
+	//  a .proto always translates to a single class, but you may want to
+	//  explicitly choose the class name).
+	javaOuterClassname?: string @protobuf(8,name=java_outer_classname)
+
+	//  If set true, then the Java code generator will generate a separate .java
+	//  file for each top-level message, enum, and service defined in the .proto
+	//  file.  Thus, these types will *not* be nested inside the outer class
+	//  named by java_outer_classname.  However, the outer class will still be
+	//  generated to contain the file's getDescriptor() method as well as any
+	//  top-level extensions defined in the file.
+	javaMultipleFiles?: bool @protobuf(10,name=java_multiple_files,"default=false")
+
+	//  This option does nothing.
+	javaGenerateEqualsAndHash?: bool @protobuf(20,name=java_generate_equals_and_hash,deprecated)
+
+	//  If set true, then the Java2 code generator will generate code that
+	//  throws an exception whenever an attempt is made to assign a non-UTF-8
+	//  byte sequence to a string field.
+	//  Message reflection will do the same.
+	//  However, an extension field still accepts non-UTF-8 byte sequences.
+	//  This option has no effect on when used with the lite runtime.
+	javaStringCheckUtf8?: bool                     @protobuf(27,name=java_string_check_utf8,"default=false")
+	optimizeFor?:         FileOptions_OptimizeMode @protobuf(9,type=OptimizeMode,name=optimize_for,"default=SPEED")
+
+	//  Sets the Go package where structs generated from this .proto will be
+	//  placed. If omitted, the Go package will be derived from the following:
+	//    - The basename of the package import path, if provided.
+	//    - Otherwise, the package statement in the .proto file, if present.
+	//    - Otherwise, the basename of the .proto file, without extension.
+	goPackage?: string @protobuf(11,name=go_package)
+
+	//  Should generic services be generated in each language?  "Generic" services
+	//  are not specific to any particular RPC system.  They are generated by the
+	//  main code generators in each language (without additional plugins).
+	//  Generic services were the only kind of service generation supported by
+	//  early versions of google.protobuf.
+	// 
+	//  Generic services are now considered deprecated in favor of using plugins
+	//  that generate code specific to your particular RPC system.  Therefore,
+	//  these default to false.  Old code which depends on generic services should
+	//  explicitly set them to true.
+	ccGenericServices?:   bool @protobuf(16,name=cc_generic_services,"default=false")
+	javaGenericServices?: bool @protobuf(17,name=java_generic_services,"default=false")
+	pyGenericServices?:   bool @protobuf(18,name=py_generic_services,"default=false")
+	phpGenericServices?:  bool @protobuf(42,name=php_generic_services,"default=false")
+
+	//  Is this file deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for everything in the file, or it will be completely ignored; in the very
+	//  least, this is a formalization for deprecating files.
+	deprecated?: bool @protobuf(23,"default=false")
+
+	//  Enables the use of arenas for the proto messages in this file. This applies
+	//  only to generated classes for C++.
+	ccEnableArenas?: bool @protobuf(31,name=cc_enable_arenas,"default=false")
+
+	//  Sets the objective c class prefix which is prepended to all objective c
+	//  generated classes from this .proto. There is no default.
+	objcClassPrefix?: string @protobuf(36,name=objc_class_prefix)
+
+	//  Namespace for generated classes; defaults to the package.
+	csharpNamespace?: string @protobuf(37,name=csharp_namespace)
+
+	//  By default Swift generators will take the proto package and CamelCase it
+	//  replacing '.' with underscore and use that to prefix the types/symbols
+	//  defined. When this options is provided, they will use this value instead
+	//  to prefix the types/symbols defined.
+	swiftPrefix?: string @protobuf(39,name=swift_prefix)
+
+	//  Sets the php class prefix which is prepended to all php generated classes
+	//  from this .proto. Default is empty.
+	phpClassPrefix?: string @protobuf(40,name=php_class_prefix)
+
+	//  Use this option to change the namespace of php generated classes. Default
+	//  is empty. When this option is empty, the package name will be used for
+	//  determining the namespace.
+	phpNamespace?: string @protobuf(41,name=php_namespace)
+
+	//  Use this option to change the namespace of php generated metadata classes.
+	//  Default is empty. When this option is empty, the proto file name will be
+	//  used for determining the namespace.
+	phpMetadataNamespace?: string @protobuf(44,name=php_metadata_namespace)
+
+	//  Use this option to change the package of ruby generated classes. Default
+	//  is empty. When this option is not set, the package name will be used for
+	//  determining the ruby package.
+	rubyPackage?: string @protobuf(45,name=ruby_package)
+
+	//  The parser stores options it doesn't recognize here.
+	//  See the documentation for the "Options" section above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+//  Generated classes can be optimized for speed or code size.
+FileOptions_OptimizeMode:
+	*"SPEED" | //  Generate complete code for parsing, serialization,
+
+	//  etc.
+	"CODE_SIZE" |
+	"LITE_RUNTIME" //  Generate code using MessageLite and the lite runtime.
+
+FileOptions_OptimizeMode_value: {
+	"SPEED":        1
+	"CODE_SIZE":    2 //  Use ReflectionOps to implement these methods.
+	"LITE_RUNTIME": 3
+}
+
+MessageOptions: {
+	//  Set true to use the old proto1 MessageSet wire format for extensions.
+	//  This is provided for backwards-compatibility with the MessageSet wire
+	//  format.  You should not use this for any other reason:  It's less
+	//  efficient, has fewer features, and is more complicated.
+	// 
+	//  The message must be defined exactly as follows:
+	//    message Foo {
+	//      option message_set_wire_format = true;
+	//      extensions 4 to max;
+	//    }
+	//  Note that the message cannot have any defined fields; MessageSets only
+	//  have extensions.
+	// 
+	//  All extensions of your type must be singular messages; e.g. they cannot
+	//  be int32s, enums, or repeated messages.
+	// 
+	//  Because this is an option, the above two restrictions are not enforced by
+	//  the protocol compiler.
+	messageSetWireFormat?: bool @protobuf(1,name=message_set_wire_format,"default=false")
+
+	//  Disables the generation of the standard "descriptor()" accessor, which can
+	//  conflict with a field of the same name.  This is meant to make migration
+	//  from proto1 easier; new code should avoid fields named "descriptor".
+	noStandardDescriptorAccessor?: bool @protobuf(2,name=no_standard_descriptor_accessor,"default=false")
+
+	//  Is this message deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for the message, or it will be completely ignored; in the very least,
+	//  this is a formalization for deprecating messages.
+	deprecated?: bool @protobuf(3,"default=false")
+
+	//  Whether the message is an automatically generated map entry type for the
+	//  maps field.
+	// 
+	//  For maps fields:
+	//      map<KeyType, ValueType> map_field = 1;
+	//  The parsed descriptor looks like:
+	//      message MapFieldEntry {
+	//          option map_entry = true;
+	//          optional KeyType key = 1;
+	//          optional ValueType value = 2;
+	//      }
+	//      repeated MapFieldEntry map_field = 1;
+	// 
+	//  Implementations may choose not to generate the map_entry=true message, but
+	//  use a native map in the target language to hold the keys and values.
+	//  The reflection APIs in such implementations still need to work as
+	//  if the field is a repeated message field.
+	// 
+	//  NOTE: Do not set the option in .proto files. Always use the maps syntax
+	//  instead. The option should only be implicitly set by the proto compiler
+	//  parser.
+	mapEntry?: bool @protobuf(7,name=map_entry)
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+FieldOptions: {
+	//  The ctype option instructs the C++ code generator to use a different
+	//  representation of the field than it normally would.  See the specific
+	//  options below.  This option is not yet implemented in the open source
+	//  release -- sorry, we'll try to include it in a future version!
+	ctype?: FieldOptions_CType @protobuf(1,type=CType,"default=STRING")
+
+	//  The packed option can be enabled for repeated primitive fields to enable
+	//  a more efficient representation on the wire. Rather than repeatedly
+	//  writing the tag and type for each element, the entire array is encoded as
+	//  a single length-delimited blob. In proto3, only explicit setting it to
+	//  false will avoid using packed encoding.
+	packed?: bool @protobuf(2)
+
+	//  The jstype option determines the JavaScript type used for values of the
+	//  field.  The option is permitted only for 64 bit integral and fixed types
+	//  (int64, uint64, sint64, fixed64, sfixed64).  A field with jstype JS_STRING
+	//  is represented as JavaScript string, which avoids loss of precision that
+	//  can happen when a large value is converted to a floating point JavaScript.
+	//  Specifying JS_NUMBER for the jstype causes the generated JavaScript code to
+	//  use the JavaScript "number" type.  The behavior of the default option
+	//  JS_NORMAL is implementation dependent.
+	// 
+	//  This option is an enum to permit additional types to be added, e.g.
+	//  goog.math.Integer.
+	jstype?: FieldOptions_JSType @protobuf(6,type=JSType,"default=JS_NORMAL")
+
+	//  Should this field be parsed lazily?  Lazy applies only to message-type
+	//  fields.  It means that when the outer message is initially parsed, the
+	//  inner message's contents will not be parsed but instead stored in encoded
+	//  form.  The inner message will actually be parsed when it is first accessed.
+	// 
+	//  This is only a hint.  Implementations are free to choose whether to use
+	//  eager or lazy parsing regardless of the value of this option.  However,
+	//  setting this option true suggests that the protocol author believes that
+	//  using lazy parsing on this field is worth the additional bookkeeping
+	//  overhead typically needed to implement it.
+	// 
+	//  This option does not affect the public interface of any generated code;
+	//  all method signatures remain the same.  Furthermore, thread-safety of the
+	//  interface is not affected by this option; const methods remain safe to
+	//  call from multiple threads concurrently, while non-const methods continue
+	//  to require exclusive access.
+	// 
+	// 
+	//  Note that implementations may choose not to check required fields within
+	//  a lazy sub-message.  That is, calling IsInitialized() on the outer message
+	//  may return true even if the inner message has missing required fields.
+	//  This is necessary because otherwise the inner message would have to be
+	//  parsed in order to perform the check, defeating the purpose of lazy
+	//  parsing.  An implementation which chooses not to check required fields
+	//  must be consistent about it.  That is, for any particular sub-message, the
+	//  implementation must either *always* check its required fields, or *never*
+	//  check its required fields, regardless of whether or not the message has
+	//  been parsed.
+	lazy?: bool @protobuf(5,"default=false")
+
+	//  Is this field deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for accessors, or it will be completely ignored; in the very least, this
+	//  is a formalization for deprecating fields.
+	deprecated?: bool @protobuf(3,"default=false")
+
+	//  For Google-internal migration only. Do not use.
+	weak?: bool @protobuf(10,"default=false")
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+FieldOptions_CType:
+	//  Default mode.
+	*"STRING" |
+	"CORD" |
+	"STRING_PIECE"
+
+FieldOptions_CType_value: {
+	"STRING":       0
+	"CORD":         1
+	"STRING_PIECE": 2
+}
+FieldOptions_JSType:
+	//  Use the default type.
+	*"JS_NORMAL" |
+
+	//  Use JavaScript strings.
+	"JS_STRING" |
+
+	//  Use JavaScript numbers.
+	"JS_NUMBER"
+
+FieldOptions_JSType_value: {
+	"JS_NORMAL": 0
+	"JS_STRING": 1
+	"JS_NUMBER": 2
+}
+
+OneofOptions: {
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+EnumOptions: {
+	//  Set this option to true to allow mapping different tag names to the same
+	//  value.
+	allowAlias?: bool @protobuf(2,name=allow_alias)
+
+	//  Is this enum deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for the enum, or it will be completely ignored; in the very least, this
+	//  is a formalization for deprecating enums.
+	deprecated?: bool @protobuf(3,"default=false")
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+EnumValueOptions: {
+	//  Is this enum value deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for the enum value, or it will be completely ignored; in the very least,
+	//  this is a formalization for deprecating enum values.
+	deprecated?: bool @protobuf(1,"default=false")
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+ServiceOptions: {
+
+	//  Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+	//    framework.  We apologize for hoarding these numbers to ourselves, but
+	//    we were already using them long before we decided to release Protocol
+	//    Buffers.
+
+	//  Is this service deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for the service, or it will be completely ignored; in the very least,
+	//  this is a formalization for deprecating services.
+	deprecated?: bool @protobuf(33,"default=false")
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+MethodOptions: {
+
+	//  Note:  Field numbers 1 through 32 are reserved for Google's internal RPC
+	//    framework.  We apologize for hoarding these numbers to ourselves, but
+	//    we were already using them long before we decided to release Protocol
+	//    Buffers.
+
+	//  Is this method deprecated?
+	//  Depending on the target platform, this can emit Deprecated annotations
+	//  for the method, or it will be completely ignored; in the very least,
+	//  this is a formalization for deprecating methods.
+	deprecated?:       bool                           @protobuf(33,"default=false")
+	idempotencyLevel?: MethodOptions_IdempotencyLevel @protobuf(34,type=IdempotencyLevel,name=idempotency_level,"default=IDEMPOTENCY_UNKNOWN")
+
+	//  The parser stores options it doesn't recognize here. See above.
+	uninterpretedOption?: [...UninterpretedOption] @protobuf(999,name=uninterpreted_option)
+}
+
+//  Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
+//  or neither? HTTP based RPC implementation may choose GET verb for safe
+//  methods, and PUT verb for idempotent methods instead of the default POST.
+MethodOptions_IdempotencyLevel:
+	*"IDEMPOTENCY_UNKNOWN" |
+	"NO_SIDE_EFFECTS" | //  implies idempotent
+	"IDEMPOTENT" //  idempotent, but may have side effects
+
+MethodOptions_IdempotencyLevel_value: {
+	"IDEMPOTENCY_UNKNOWN": 0
+	"NO_SIDE_EFFECTS":     1
+	"IDEMPOTENT":          2
+}
+
+//  A message representing a option the parser does not recognize. This only
+//  appears in options protos created by the compiler::Parser class.
+//  DescriptorPool resolves these when building Descriptor objects. Therefore,
+//  options protos in descriptor objects (e.g. returned by Descriptor::options(),
+//  or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+//  in them.
+UninterpretedOption: {
+	name?: [...UninterpretedOption_NamePart] @protobuf(2,type=NamePart)
+
+	//  The value of the uninterpreted option, in whatever type the tokenizer
+	//  identified it as during parsing. Exactly one of these should be set.
+	identifierValue?:  string  @protobuf(3,name=identifier_value)
+	positiveIntValue?: uint64  @protobuf(4,name=positive_int_value)
+	negativeIntValue?: int64   @protobuf(5,name=negative_int_value)
+	doubleValue?:      float64 @protobuf(6,type=double,name=double_value)
+	stringValue?:      bytes   @protobuf(7,name=string_value)
+	aggregateValue?:   string  @protobuf(8,name=aggregate_value)
+}
+
+//  The name of the uninterpreted option.  Each string represents a segment in
+//  a dot-separated name.  is_extension is true iff a segment represents an
+//  extension (denoted with parentheses in options specs in .proto files).
+//  E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+//  "foo.(bar.baz).qux".
+UninterpretedOption_NamePart: {
+	namePart?:    string @protobuf(1,name=name_part)
+	isExtension?: bool   @protobuf(2,name=is_extension)
+}
+
+//  Encapsulates information about the original source file from which a
+//  FileDescriptorProto was generated.
+SourceCodeInfo: {
+	//  A Location identifies a piece of source code in a .proto file which
+	//  corresponds to a particular definition.  This information is intended
+	//  to be useful to IDEs, code indexers, documentation generators, and similar
+	//  tools.
+	// 
+	//  For example, say we have a file like:
+	//    message Foo {
+	//      optional string foo = 1;
+	//    }
+	//  Let's look at just the field definition:
+	//    optional string foo = 1;
+	//    ^       ^^     ^^  ^  ^^^
+	//    a       bc     de  f  ghi
+	//  We have the following locations:
+	//    span   path               represents
+	//    [a,i)  [ 4, 0, 2, 0 ]     The whole field definition.
+	//    [a,b)  [ 4, 0, 2, 0, 4 ]  The label (optional).
+	//    [c,d)  [ 4, 0, 2, 0, 5 ]  The type (string).
+	//    [e,f)  [ 4, 0, 2, 0, 1 ]  The name (foo).
+	//    [g,h)  [ 4, 0, 2, 0, 3 ]  The number (1).
+	// 
+	//  Notes:
+	//  - A location may refer to a repeated field itself (i.e. not to any
+	//    particular index within it).  This is used whenever a set of elements are
+	//    logically enclosed in a single code segment.  For example, an entire
+	//    extend block (possibly containing multiple extension definitions) will
+	//    have an outer location whose path refers to the "extensions" repeated
+	//    field without an index.
+	//  - Multiple locations may have the same path.  This happens when a single
+	//    logical declaration is spread out across multiple places.  The most
+	//    obvious example is the "extend" block again -- there may be multiple
+	//    extend blocks in the same scope, each of which will have the same path.
+	//  - A location's span is not always a subset of its parent's span.  For
+	//    example, the "extendee" of an extension declaration appears at the
+	//    beginning of the "extend" block and is shared by all extensions within
+	//    the block.
+	//  - Just because a location's span is a subset of some other location's span
+	//    does not mean that it is a descendant.  For example, a "group" defines
+	//    both a type and a field in a single declaration.  Thus, the locations
+	//    corresponding to the type and field and their components will overlap.
+	//  - Code which tries to interpret locations should probably be designed to
+	//    ignore those that it doesn't understand, as more types of locations could
+	//    be recorded in the future.
+	location?: [...SourceCodeInfo_Location] @protobuf(1,type=Location)
+}
+
+SourceCodeInfo_Location: {
+	//  Identifies which part of the FileDescriptorProto was defined at this
+	//  location.
+	// 
+	//  Each element is a field number or an index.  They form a path from
+	//  the root FileDescriptorProto to the place where the definition.  For
+	//  example, this path:
+	//    [ 4, 3, 2, 7, 1 ]
+	//  refers to:
+	//    file.message_type(3)  // 4, 3
+	//        .field(7)         // 2, 7
+	//        .name()           // 1
+	//  This is because FileDescriptorProto.message_type has field number 4:
+	//    repeated DescriptorProto message_type = 4;
+	//  and DescriptorProto.field has field number 2:
+	//    repeated FieldDescriptorProto field = 2;
+	//  and FieldDescriptorProto.name has field number 1:
+	//    optional string name = 1;
+	// 
+	//  Thus, the above path gives the location of a field name.  If we removed
+	//  the last element:
+	//    [ 4, 3, 2, 7 ]
+	//  this path refers to the whole field declaration (from the beginning
+	//  of the label to the terminating semicolon).
+	path?: [...int32] @protobuf(1,packed)
+
+	//  Always has exactly three or four elements: start line, start column,
+	//  end line (optional, otherwise assumed same as start line), end column.
+	//  These are packed into a single field for efficiency.  Note that line
+	//  and column numbers are zero-based -- typically you will want to add
+	//  1 to each before displaying to a user.
+	span?: [...int32] @protobuf(2,packed)
+
+	//  If this SourceCodeInfo represents a complete declaration, these are any
+	//  comments appearing before and after the declaration which appear to be
+	//  attached to the declaration.
+	// 
+	//  A series of line comments appearing on consecutive lines, with no other
+	//  tokens appearing on those lines, will be treated as a single comment.
+	// 
+	//  leading_detached_comments will keep paragraphs of comments that appear
+	//  before (but not connected to) the current element. Each paragraph,
+	//  separated by empty lines, will be one comment element in the repeated
+	//  field.
+	// 
+	//  Only the comment content is provided; comment markers (e.g. //) are
+	//  stripped out.  For block comments, leading whitespace and an asterisk
+	//  will be stripped from the beginning of each line other than the first.
+	//  Newlines are included in the output.
+	// 
+	//  Examples:
+	// 
+	//    optional int32 foo = 1;  // Comment attached to foo.
+	//    // Comment attached to bar.
+	//    optional int32 bar = 2;
+	// 
+	//    optional string baz = 3;
+	//    // Comment attached to baz.
+	//    // Another line attached to baz.
+	// 
+	//    // Comment attached to qux.
+	//    //
+	//    // Another line attached to qux.
+	//    optional double qux = 4;
+	// 
+	//    // Detached comment for corge. This is not leading or trailing comments
+	//    // to qux or corge because there are blank lines separating it from
+	//    // both.
+	// 
+	//    // Detached comment for corge paragraph 2.
+	// 
+	//    optional string corge = 5;
+	//    /* Block comment attached
+	//     * to corge.  Leading asterisks
+	//     * will be removed. */
+	//    /* Block comment attached to
+	//     * grault. */
+	//    optional int32 grault = 6;
+	// 
+	//    // ignored detached comments.
+	leadingComments?:  string @protobuf(3,name=leading_comments)
+	trailingComments?: string @protobuf(4,name=trailing_comments)
+	leadingDetachedComments?: [...string] @protobuf(6,name=leading_detached_comments)
+}
+
+//  Describes the relationship between generated code and its original source
+//  file. A GeneratedCodeInfo message is associated with only one generated
+//  source file, but may contain references to different source .proto files.
+GeneratedCodeInfo: {
+	//  An Annotation connects some span of text in generated code to an element
+	//  of its generating .proto file.
+	annotation?: [...GeneratedCodeInfo_Annotation] @protobuf(1,type=Annotation)
+}
+
+GeneratedCodeInfo_Annotation: {
+	//  Identifies the element in the original source .proto file. This field
+	//  is formatted the same as SourceCodeInfo.Location.path.
+	path?: [...int32] @protobuf(1,packed)
+
+	//  Identifies the filesystem path to the original source .proto.
+	sourceFile?: string @protobuf(2,name=source_file)
+
+	//  Identifies the starting offset in bytes in the generated code
+	//  that relates to the identified object.
+	begin?: int32 @protobuf(3)
+
+	//  Identifies the ending offset in bytes in the generated code that
+	//  relates to the identified offset. The end offset should be one past
+	//  the last relevant byte (so the length of the text = end - begin).
+	end?: int32 @protobuf(4)
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/any/any_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/any/any_proto_gen.cue
new file mode 100644
index 0000000..43f43b9
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/any/any_proto_gen.cue
@@ -0,0 +1,146 @@
+
+//  Protocol Buffers - Google's data interchange format
+//  Copyright 2008 Google Inc.  All rights reserved.
+//  https://developers.google.com/protocol-buffers/
+// 
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions are
+//  met:
+// 
+//      * Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//      * Redistributions in binary form must reproduce the above
+//  copyright notice, this list of conditions and the following disclaimer
+//  in the documentation and/or other materials provided with the
+//  distribution.
+//      * Neither the name of Google Inc. nor the names of its
+//  contributors may be used to endorse or promote products derived from
+//  this software without specific prior written permission.
+// 
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+package any
+
+//  `Any` contains an arbitrary serialized protocol buffer message along with a
+//  URL that describes the type of the serialized message.
+// 
+//  Protobuf library provides support to pack/unpack Any values in the form
+//  of utility functions or additional generated methods of the Any type.
+// 
+//  Example 1: Pack and unpack a message in C++.
+// 
+//      Foo foo = ...;
+//      Any any;
+//      any.PackFrom(foo);
+//      ...
+//      if (any.UnpackTo(&foo)) {
+//        ...
+//      }
+// 
+//  Example 2: Pack and unpack a message in Java.
+// 
+//      Foo foo = ...;
+//      Any any = Any.pack(foo);
+//      ...
+//      if (any.is(Foo.class)) {
+//        foo = any.unpack(Foo.class);
+//      }
+// 
+//   Example 3: Pack and unpack a message in Python.
+// 
+//      foo = Foo(...)
+//      any = Any()
+//      any.Pack(foo)
+//      ...
+//      if any.Is(Foo.DESCRIPTOR):
+//        any.Unpack(foo)
+//        ...
+// 
+//   Example 4: Pack and unpack a message in Go
+// 
+//       foo := &pb.Foo{...}
+//       any, err := ptypes.MarshalAny(foo)
+//       ...
+//       foo := &pb.Foo{}
+//       if err := ptypes.UnmarshalAny(any, foo); err != nil {
+//         ...
+//       }
+// 
+//  The pack methods provided by protobuf library will by default use
+//  'type.googleapis.com/full.type.name' as the type URL and the unpack
+//  methods only use the fully qualified type name after the last '/'
+//  in the type URL, for example "foo.bar.com/x/y.z" will yield type
+//  name "y.z".
+// 
+// 
+//  JSON
+//  ====
+//  The JSON representation of an `Any` value uses the regular
+//  representation of the deserialized, embedded message, with an
+//  additional field `@type` which contains the type URL. Example:
+// 
+//      package google.profile;
+//      message Person {
+//        string first_name = 1;
+//        string last_name = 2;
+//      }
+// 
+//      {
+//        "@type": "type.googleapis.com/google.profile.Person",
+//        "firstName": <string>,
+//        "lastName": <string>
+//      }
+// 
+//  If the embedded message type is well-known and has a custom JSON
+//  representation, that representation will be embedded adding a field
+//  `value` which holds the custom JSON in addition to the `@type`
+//  field. Example (for message [google.protobuf.Duration][]):
+// 
+//      {
+//        "@type": "type.googleapis.com/google.protobuf.Duration",
+//        "value": "1.212s"
+//      }
+// 
+Any: {
+	//  A URL/resource name that uniquely identifies the type of the serialized
+	//  protocol buffer message. This string must contain at least
+	//  one "/" character. The last segment of the URL's path must represent
+	//  the fully qualified name of the type (as in
+	//  `path/google.protobuf.Duration`). The name should be in a canonical form
+	//  (e.g., leading "." is not accepted).
+	// 
+	//  In practice, teams usually precompile into the binary all types that they
+	//  expect it to use in the context of Any. However, for URLs which use the
+	//  scheme `http`, `https`, or no scheme, one can optionally set up a type
+	//  server that maps type URLs to message definitions as follows:
+	// 
+	//  * If no scheme is provided, `https` is assumed.
+	//  * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+	//    value in binary format, or produce an error.
+	//  * Applications are allowed to cache lookup results based on the
+	//    URL, or have them precompiled into a binary to avoid any
+	//    lookup. Therefore, binary compatibility needs to be preserved
+	//    on changes to types. (Use versioned type names to manage
+	//    breaking changes.)
+	// 
+	//  Note: this functionality is not currently available in the official
+	//  protobuf release, and it is not used for type URLs beginning with
+	//  type.googleapis.com.
+	// 
+	//  Schemes other than `http`, `https` (or the empty scheme) might be
+	//  used with implementation specific semantics.
+	// 
+	typeUrl?: string @protobuf(1,name=type_url)
+
+	//  Must be a valid serialized protocol buffer of the above specified type.
+	value?: bytes @protobuf(2)
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/duration/duration_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/duration/duration_proto_gen.cue
new file mode 100644
index 0000000..bca02c4
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/duration/duration_proto_gen.cue
@@ -0,0 +1,106 @@
+
+//  Protocol Buffers - Google's data interchange format
+//  Copyright 2008 Google Inc.  All rights reserved.
+//  https://developers.google.com/protocol-buffers/
+// 
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions are
+//  met:
+// 
+//      * Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//      * Redistributions in binary form must reproduce the above
+//  copyright notice, this list of conditions and the following disclaimer
+//  in the documentation and/or other materials provided with the
+//  distribution.
+//      * Neither the name of Google Inc. nor the names of its
+//  contributors may be used to endorse or promote products derived from
+//  this software without specific prior written permission.
+// 
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+package duration
+
+//  A Duration represents a signed, fixed-length span of time represented
+//  as a count of seconds and fractions of seconds at nanosecond
+//  resolution. It is independent of any calendar and concepts like "day"
+//  or "month". It is related to Timestamp in that the difference between
+//  two Timestamp values is a Duration and it can be added or subtracted
+//  from a Timestamp. Range is approximately +-10,000 years.
+// 
+//  # Examples
+// 
+//  Example 1: Compute Duration from two Timestamps in pseudo code.
+// 
+//      Timestamp start = ...;
+//      Timestamp end = ...;
+//      Duration duration = ...;
+// 
+//      duration.seconds = end.seconds - start.seconds;
+//      duration.nanos = end.nanos - start.nanos;
+// 
+//      if (duration.seconds < 0 && duration.nanos > 0) {
+//        duration.seconds += 1;
+//        duration.nanos -= 1000000000;
+//      } else if (durations.seconds > 0 && duration.nanos < 0) {
+//        duration.seconds -= 1;
+//        duration.nanos += 1000000000;
+//      }
+// 
+//  Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+// 
+//      Timestamp start = ...;
+//      Duration duration = ...;
+//      Timestamp end = ...;
+// 
+//      end.seconds = start.seconds + duration.seconds;
+//      end.nanos = start.nanos + duration.nanos;
+// 
+//      if (end.nanos < 0) {
+//        end.seconds -= 1;
+//        end.nanos += 1000000000;
+//      } else if (end.nanos >= 1000000000) {
+//        end.seconds += 1;
+//        end.nanos -= 1000000000;
+//      }
+// 
+//  Example 3: Compute Duration from datetime.timedelta in Python.
+// 
+//      td = datetime.timedelta(days=3, minutes=10)
+//      duration = Duration()
+//      duration.FromTimedelta(td)
+// 
+//  # JSON Mapping
+// 
+//  In JSON format, the Duration type is encoded as a string rather than an
+//  object, where the string ends in the suffix "s" (indicating seconds) and
+//  is preceded by the number of seconds, with nanoseconds expressed as
+//  fractional seconds. For example, 3 seconds with 0 nanoseconds should be
+//  encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
+//  be expressed in JSON format as "3.000000001s", and 3 seconds and 1
+//  microsecond should be expressed in JSON format as "3.000001s".
+// 
+// 
+Duration: {
+	//  Signed seconds of the span of time. Must be from -315,576,000,000
+	//  to +315,576,000,000 inclusive. Note: these bounds are computed from:
+	//  60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+	seconds?: int64 @protobuf(1)
+
+	//  Signed fractions of a second at nanosecond resolution of the span
+	//  of time. Durations less than one second are represented with a 0
+	//  `seconds` field and a positive or negative `nanos` field. For durations
+	//  of one second or more, a non-zero value for the `nanos` field must be
+	//  of the same sign as the `seconds` field. Must be from -999,999,999
+	//  to +999,999,999 inclusive.
+	nanos?: int32 @protobuf(2)
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/timestamp/timestamp_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/timestamp/timestamp_proto_gen.cue
new file mode 100644
index 0000000..f11f6e3
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/github.com/golang/protobuf/ptypes/timestamp/timestamp_proto_gen.cue
@@ -0,0 +1,128 @@
+
+//  Protocol Buffers - Google's data interchange format
+//  Copyright 2008 Google Inc.  All rights reserved.
+//  https://developers.google.com/protocol-buffers/
+// 
+//  Redistribution and use in source and binary forms, with or without
+//  modification, are permitted provided that the following conditions are
+//  met:
+// 
+//      * Redistributions of source code must retain the above copyright
+//  notice, this list of conditions and the following disclaimer.
+//      * Redistributions in binary form must reproduce the above
+//  copyright notice, this list of conditions and the following disclaimer
+//  in the documentation and/or other materials provided with the
+//  distribution.
+//      * Neither the name of Google Inc. nor the names of its
+//  contributors may be used to endorse or promote products derived from
+//  this software without specific prior written permission.
+// 
+//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+package timestamp
+
+//  A Timestamp represents a point in time independent of any time zone or local
+//  calendar, encoded as a count of seconds and fractions of seconds at
+//  nanosecond resolution. The count is relative to an epoch at UTC midnight on
+//  January 1, 1970, in the proleptic Gregorian calendar which extends the
+//  Gregorian calendar backwards to year one.
+// 
+//  All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
+//  second table is needed for interpretation, using a [24-hour linear
+//  smear](https://developers.google.com/time/smear).
+// 
+//  The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
+//  restricting to that range, we ensure that we can convert to and from [RFC
+//  3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
+// 
+//  # Examples
+// 
+//  Example 1: Compute Timestamp from POSIX `time()`.
+// 
+//      Timestamp timestamp;
+//      timestamp.set_seconds(time(NULL));
+//      timestamp.set_nanos(0);
+// 
+//  Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+// 
+//      struct timeval tv;
+//      gettimeofday(&tv, NULL);
+// 
+//      Timestamp timestamp;
+//      timestamp.set_seconds(tv.tv_sec);
+//      timestamp.set_nanos(tv.tv_usec * 1000);
+// 
+//  Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+// 
+//      FILETIME ft;
+//      GetSystemTimeAsFileTime(&ft);
+//      UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+// 
+//      // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+//      // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+//      Timestamp timestamp;
+//      timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+//      timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+// 
+//  Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+// 
+//      long millis = System.currentTimeMillis();
+// 
+//      Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+//          .setNanos((int) ((millis % 1000) * 1000000)).build();
+// 
+// 
+//  Example 5: Compute Timestamp from current time in Python.
+// 
+//      timestamp = Timestamp()
+//      timestamp.GetCurrentTime()
+// 
+//  # JSON Mapping
+// 
+//  In JSON format, the Timestamp type is encoded as a string in the
+//  [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
+//  format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
+//  where {year} is always expressed using four digits while {month}, {day},
+//  {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
+//  seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
+//  are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
+//  is required. A proto3 JSON serializer should always use UTC (as indicated by
+//  "Z") when printing the Timestamp type and a proto3 JSON parser should be
+//  able to accept both UTC and other timezones (as indicated by an offset).
+// 
+//  For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
+//  01:30 UTC on January 15, 2017.
+// 
+//  In JavaScript, one can convert a Date object to this format using the
+//  standard
+//  [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
+//  method. In Python, a standard `datetime.datetime` object can be converted
+//  to this format using
+//  [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
+//  the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
+//  the Joda Time's [`ISODateTimeFormat.dateTime()`](
+//  http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
+//  ) to obtain a formatter capable of generating timestamps in this format.
+// 
+// 
+Timestamp: {
+	//  Represents seconds of UTC time since Unix epoch
+	//  1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+	//  9999-12-31T23:59:59Z inclusive.
+	seconds?: int64 @protobuf(1)
+
+	//  Non-negative fractions of a second at nanosecond resolution. Negative
+	//  second values with fractions must still have non-negative nanos values
+	//  that count forward in time. Must be from 0 to 999,999,999
+	//  inclusive.
+	nanos?: int32 @protobuf(2)
+}
diff --git a/encoding/protobuf/testdata/istio.io/api/pkg/google.golang.org/genproto/googleapis/rpc/status/status_proto_gen.cue b/encoding/protobuf/testdata/istio.io/api/pkg/google.golang.org/genproto/googleapis/rpc/status/status_proto_gen.cue
new file mode 100644
index 0000000..e1348a8
--- /dev/null
+++ b/encoding/protobuf/testdata/istio.io/api/pkg/google.golang.org/genproto/googleapis/rpc/status/status_proto_gen.cue
@@ -0,0 +1,84 @@
+
+//  Copyright 2017 Google Inc.
+// 
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at
+// 
+//      http://www.apache.org/licenses/LICENSE-2.0
+// 
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+package status
+
+//  The `Status` type defines a logical error model that is suitable for
+//  different programming environments, including REST APIs and RPC APIs. It is
+//  used by [gRPC](https://github.com/grpc). The error model is designed to be:
+// 
+//  - Simple to use and understand for most users
+//  - Flexible enough to meet unexpected needs
+// 
+//  # Overview
+// 
+//  The `Status` message contains three pieces of data: error code, error
+//  message, and error details. The error code should be an enum value of
+//  [google.rpc.Code][google.rpc.Code], but it may accept additional error codes
+//  if needed.  The error message should be a developer-facing English message
+//  that helps developers *understand* and *resolve* the error. If a localized
+//  user-facing error message is needed, put the localized message in the error
+//  details or localize it in the client. The optional error details may contain
+//  arbitrary information about the error. There is a predefined set of error
+//  detail types in the package `google.rpc` that can be used for common error
+//  conditions.
+// 
+//  # Language mapping
+// 
+//  The `Status` message is the logical representation of the error model, but it
+//  is not necessarily the actual wire format. When the `Status` message is
+//  exposed in different client libraries and different wire protocols, it can be
+//  mapped differently. For example, it will likely be mapped to some exceptions
+//  in Java, but more likely mapped to some error codes in C.
+// 
+//  # Other uses
+// 
+//  The error model and the `Status` message can be used in a variety of
+//  environments, either with or without APIs, to provide a
+//  consistent developer experience across different environments.
+// 
+//  Example uses of this error model include:
+// 
+//  - Partial errors. If a service needs to return partial errors to the client,
+//      it may embed the `Status` in the normal response to indicate the partial
+//      errors.
+// 
+//  - Workflow errors. A typical workflow has multiple steps. Each step may
+//      have a `Status` message for error reporting.
+// 
+//  - Batch operations. If a client uses batch request and batch response, the
+//      `Status` message should be used directly inside batch response, one for
+//      each error sub-response.
+// 
+//  - Asynchronous operations. If an API call embeds asynchronous operation
+//      results in its response, the status of those operations should be
+//      represented directly using the `Status` message.
+// 
+//  - Logging. If some API errors are stored in logs, the message `Status` could
+//      be used directly after any stripping needed for security/privacy reasons.
+Status: {
+	//  The status code, which should be an enum value of
+	//  [google.rpc.Code][google.rpc.Code].
+	code?: int32 @protobuf(1)
+
+	//  A developer-facing error message, which should be in English. Any
+	//  user-facing error message should be localized and sent in the
+	//  [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+	//  by the client.
+	message?: string @protobuf(2)
+
+	//  A list of messages that carry the error details.  There is a common set of
+	//  message types for APIs to use.
+	details?: [...] @protobuf(3,type=google.protobuf.Any)
+}
diff --git a/encoding/protobuf/types.go b/encoding/protobuf/types.go
index ba260f9..4538a01 100644
--- a/encoding/protobuf/types.go
+++ b/encoding/protobuf/types.go
@@ -49,12 +49,13 @@
 }
 
 var timePkg = &protoConverter{
+	id:        "time",
 	goPkg:     "time",
 	goPkgPath: "time",
 }
 
 func (p *protoConverter) setBuiltin(from, to string, pkg *protoConverter) {
-	p.scope[0][from] = mapping{to, pkg}
+	p.scope[0][from] = mapping{to, "", pkg}
 }
 
 func (p *protoConverter) mapBuiltinPackage(pos scanner.Position, file string, required bool) {
diff --git a/encoding/protobuf/util.go b/encoding/protobuf/util.go
index d1040d0..38521ab 100644
--- a/encoding/protobuf/util.go
+++ b/encoding/protobuf/util.go
@@ -71,17 +71,6 @@
 	return cg
 }
 
-func quote(s string) string {
-	if !strings.ContainsAny(s, `"\`) {
-		return s
-	}
-	esc := `\#`
-	for strings.Contains(s, esc) {
-		esc += "#"
-	}
-	return esc[1:] + `"` + s + `"` + esc[1:]
-}
-
 func labelName(s string) string {
 	split := strings.Split(s, "_")
 	for i := 1; i < len(split); i++ {