protoveneer: remove

Change-Id: I9bc97e6fcaef6fa0bc20ae1105493c81017ffe3a
Reviewed-on: https://go-review.googlesource.com/c/exp/+/554718
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
diff --git a/protoveneer/README.md b/protoveneer/README.md
deleted file mode 100644
index 95283c7..0000000
--- a/protoveneer/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# The protoveneer tool
-
-Protoveneer is an experimental tool that generates idiomatic Go types that
-correspond to protocol buffer messages and enums -- a veneer on top of the proto
-layer.
diff --git a/protoveneer/cmd/protoveneer/config.go b/protoveneer/cmd/protoveneer/config.go
deleted file mode 100644
index 0907df0..0000000
--- a/protoveneer/cmd/protoveneer/config.go
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"errors"
-	"fmt"
-	"os"
-
-	"gopkg.in/yaml.v3"
-)
-
-// config holds the configuration for a package.
-type config struct {
-	Package         string
-	ProtoImportPath string `yaml:"protoImportPath"`
-	// Import path for the support package needed by the generated code.
-	SupportImportPath string `yaml:"supportImportPath"`
-
-	// The types to process. Only these types and the types they depend
-	// on will be output.
-	// The key is the name of the proto type.
-	Types map[string]*typeConfig
-	// Omit the types in this list, even if they would normally be output.
-	// Elements can be globs.
-	OmitTypes []string `yaml:"omitTypes"`
-	// Converter functions for types not in the proto package.
-	// Each value should be "tofunc, fromfunc"
-	Converters map[string]string
-}
-
-type typeConfig struct {
-	// The name for the veneer type, if different.
-	Name string
-	// The prefix of the proto enum values. It will be removed.
-	ProtoPrefix string `yaml:"protoPrefix"`
-	// The prefix for the veneer enum values, if different from the type name.
-	VeneerPrefix string `yaml:"veneerPrefix"`
-	// Overrides for enum values.
-	ValueNames map[string]string `yaml:"valueNames"`
-	// Overrides for field types. Map key is proto field name.
-	Fields map[string]fieldConfig
-	// Custom conversion functions: "tofunc, fromfunc"
-	ConvertToFrom string `yaml:"convertToFrom"`
-	// Doc string for the type, omitting the initial type name.
-	Doc string
-	// Verb to place after type name in doc. Default: "is".
-	// Ignored if Doc is non-empty.
-	DocVerb string `yaml:"docVerb"`
-}
-
-type fieldConfig struct {
-	Name string // veneer name
-	Type string // veneer type
-	// Omit from output.
-	Omit bool
-}
-
-func (c *config) init() {
-	for protoName, tc := range c.Types {
-		if tc == nil {
-			tc = &typeConfig{Name: protoName}
-			c.Types[protoName] = tc
-		}
-		if tc.Name == "" {
-			tc.Name = protoName
-		}
-		tc.init()
-	}
-}
-
-func (tc *typeConfig) init() {
-	if tc.VeneerPrefix == "" {
-		tc.VeneerPrefix = tc.Name
-	}
-}
-
-func readConfigFile(filename string) (*config, error) {
-	if filename == "" {
-		return nil, errors.New("missing config file")
-	}
-	f, err := os.Open(filename)
-	if err != nil {
-		return nil, err
-	}
-	defer f.Close()
-	dec := yaml.NewDecoder(f)
-	dec.KnownFields(true)
-
-	var c config
-	if err := dec.Decode(&c); err != nil {
-		return nil, fmt.Errorf("reading %s: %w", filename, err)
-	}
-	c.init()
-	return &c, nil
-}
diff --git a/protoveneer/cmd/protoveneer/converters.go b/protoveneer/cmd/protoveneer/converters.go
deleted file mode 100644
index a9afd70..0000000
--- a/protoveneer/cmd/protoveneer/converters.go
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import "fmt"
-
-// A converter generates code to convert between a proto type and a veneer type.
-type converter interface {
-	// genFrom returns code to convert from proto to veneer.
-	genFrom(string) string
-	// genTo returns code to convert to proto from veneer.
-	genTo(string) string
-	// These return the function argument to Transform{Slice,MapValues}, or "" if we don't need it.
-	genTransformFrom() string
-	genTransformTo() string
-}
-
-// An identityConverter does no conversion.
-type identityConverter struct{}
-
-func (identityConverter) genFrom(arg string) string { return arg }
-func (identityConverter) genTo(arg string) string   { return arg }
-func (identityConverter) genTransformFrom() string  { return "" }
-func (identityConverter) genTransformTo() string    { return "" }
-
-// A derefConverter converts between T in the veneer and *T in the proto.
-type derefConverter struct{}
-
-func (derefConverter) genFrom(arg string) string { return fmt.Sprintf("support.DerefOrZero(%s)", arg) }
-func (derefConverter) genTo(arg string) string   { return fmt.Sprintf("support.AddrOrNil(%s)", arg) }
-func (derefConverter) genTransformFrom() string  { panic("can't handle deref slices") }
-func (derefConverter) genTransformTo() string    { panic("can't handle deref slices") }
-
-type enumConverter struct {
-	protoName, veneerName string
-}
-
-func (c enumConverter) genFrom(arg string) string {
-	return fmt.Sprintf("%s(%s)", c.veneerName, arg)
-}
-
-func (c enumConverter) genTransformFrom() string {
-	return fmt.Sprintf("func(p pb.%s) %s { return %s }", c.protoName, c.veneerName, c.genFrom("p"))
-}
-
-func (c enumConverter) genTo(arg string) string {
-	return fmt.Sprintf("pb.%s(%s)", c.protoName, arg)
-}
-
-func (c enumConverter) genTransformTo() string {
-	return fmt.Sprintf("func(v %s) pb.%s { return %s }", c.veneerName, c.protoName, c.genTo("v"))
-}
-
-type protoConverter struct {
-	veneerName string
-}
-
-func (c protoConverter) genFrom(arg string) string {
-	return fmt.Sprintf("(%s{}).fromProto(%s)", c.veneerName, arg)
-}
-
-func (c protoConverter) genTransformFrom() string {
-	return fmt.Sprintf("(%s{}).fromProto", c.veneerName)
-}
-
-func (c protoConverter) genTo(arg string) string {
-	return fmt.Sprintf("%s.toProto()", arg)
-}
-
-func (c protoConverter) genTransformTo() string {
-	return fmt.Sprintf("(*%s).toProto", c.veneerName)
-}
-
-type customConverter struct {
-	toFunc, fromFunc string
-}
-
-func (c customConverter) genFrom(arg string) string {
-	return fmt.Sprintf("%s(%s)", c.fromFunc, arg)
-}
-
-func (c customConverter) genTransformFrom() string { return c.fromFunc }
-
-func (c customConverter) genTo(arg string) string {
-	return fmt.Sprintf("%s(%s)", c.toFunc, arg)
-}
-
-func (c customConverter) genTransformTo() string { return c.toFunc }
-
-type sliceConverter struct {
-	eltConverter converter
-}
-
-func (c sliceConverter) genFrom(arg string) string {
-	if fn := c.eltConverter.genTransformFrom(); fn != "" {
-		return fmt.Sprintf("support.TransformSlice(%s, %s)", arg, fn)
-	}
-	return c.eltConverter.genFrom(arg)
-}
-
-func (c sliceConverter) genTo(arg string) string {
-	if fn := c.eltConverter.genTransformTo(); fn != "" {
-		return fmt.Sprintf("support.TransformSlice(%s, %s)", arg, fn)
-	}
-	return c.eltConverter.genTo(arg)
-}
-
-func (c sliceConverter) genTransformTo() string {
-	panic("sliceConverter.genToSlice called")
-}
-
-func (c sliceConverter) genTransformFrom() string {
-	panic("sliceConverter.genFromSlice called")
-}
-
-// Only the values are converted.
-type mapConverter struct {
-	valueConverter converter
-}
-
-func (c mapConverter) genFrom(arg string) string {
-	if fn := c.valueConverter.genTransformFrom(); fn != "" {
-		return fmt.Sprintf("support.TransformMapValues(%s, %s)", arg, fn)
-	}
-	return c.valueConverter.genFrom(arg)
-}
-
-func (c mapConverter) genTo(arg string) string {
-	if fn := c.valueConverter.genTransformTo(); fn != "" {
-		return fmt.Sprintf("support.TransformMapValues(%s, %s)", arg, fn)
-	}
-	return c.valueConverter.genTo(arg)
-}
-
-func (c mapConverter) genTransformTo() string {
-	panic("mapConverter.genToSlice called")
-}
-
-func (c mapConverter) genTransformFrom() string {
-	panic("mapConverter.genFromSlice called")
-}
diff --git a/protoveneer/cmd/protoveneer/protoveneer.go b/protoveneer/cmd/protoveneer/protoveneer.go
deleted file mode 100644
index bfe36ce..0000000
--- a/protoveneer/cmd/protoveneer/protoveneer.go
+++ /dev/null
@@ -1,856 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// protoveneer generates idiomatic Go types that correspond to protocol
-// buffer messages and enums -- a veneer on top of the proto layer.
-//
-// # Relationship to GAPICs
-//
-// GAPICs and this tool complement each other.
-//
-// GAPICs have client types and idiomatic methods on them that correspond to
-// RPCs. They focus on the RPC part of a service. A GAPIC relies on the
-// underlying protocol buffer types for the request and response types, and all
-// the types that these refer to.
-//
-// protoveener generates Go types that correspond to proto messages and enums,
-// including requests and responses if desired. It doesn't touch the RPC parts
-// of the proto definition.
-//
-// # Configuration
-//
-// protoveneer requires significant configuration to produce good results.
-// See the config type in config.go and the config.yaml files in the testdata
-// subdirectories to understand how to write configuration.
-//
-// # Support functions
-//
-// protoveneer generates code that relies on a few support functions. These live
-// in the support subdirectory. You should copy the contents of this directory
-// to a location of your choice, and add "supportImportPath" to your config to
-// refer to that directory's import path.
-//
-// # Unhandled features
-//
-// There is no support for oneofs. Omit the oneof type and write custom code.
-// However, the types of the individual oneof cases can be generated.
-package main
-
-// TODO:
-// - have omitFields on a TypeConfig, like omitTypes
-// - Instead of parseCustomConverter, accept a list. Users can use the inline form
-//   to be compact.
-// - Check that a configured field is actually in the type.
-
-import (
-	"bytes"
-	"context"
-	"errors"
-	"flag"
-	"fmt"
-	"go/ast"
-	"go/format"
-	"go/parser"
-	"go/token"
-	"io"
-	"log"
-	"os"
-	"path"
-	"path/filepath"
-	"sort"
-	"strings"
-	"text/template"
-	"time"
-	"unicode"
-)
-
-var (
-	outputDir = flag.String("outdir", "", "directory to write to, or '-' for stdout")
-	noFormat  = flag.Bool("nofmt", false, "do not format output")
-)
-
-func main() {
-	log.SetPrefix("protoveneer: ")
-	log.SetFlags(0)
-	flag.Usage = func() {
-		out := flag.CommandLine.Output()
-		fmt.Fprintf(out, "usage: protoveneer CONFIG.yaml DIR_WITH_pb.go_FILES\n")
-		flag.PrintDefaults()
-	}
-	flag.Parse()
-
-	if err := run(context.Background(), flag.Arg(0), flag.Arg(1), *outputDir); err != nil {
-		log.Fatal(err)
-	}
-}
-
-func run(ctx context.Context, configFile, pbDir, outDir string) error {
-	config, err := readConfigFile(configFile)
-	if err != nil {
-		return err
-	}
-
-	fset := token.NewFileSet()
-	pkg, err := parseDir(fset, pbDir)
-	if err != nil {
-		return err
-	}
-
-	src, err := generate(config, pkg, fset)
-	if err != nil {
-		return err
-	}
-	if !*noFormat {
-		src, err = format.Source(src)
-		if err != nil {
-			return err
-		}
-	}
-
-	if outDir == "-" {
-		fmt.Printf("%s\n", src)
-	} else {
-		outfile := fmt.Sprintf("%s_veneer.gen.go", pkg.Name)
-		if outDir != "" {
-			outfile = filepath.Join(outDir, outfile)
-		}
-		if err := os.WriteFile(outfile, src, 0660); err != nil {
-			log.Fatal(err)
-		}
-		fmt.Printf("wrote %s\n", outfile)
-	}
-	return nil
-}
-
-func parseDir(fset *token.FileSet, dir string) (*ast.Package, error) {
-	pkgs, err := parser.ParseDir(fset, dir, nil, parser.ParseComments)
-	if err != nil {
-		return nil, err
-	}
-	if len(pkgs) > 2 {
-		return nil, errors.New("too many packages")
-	}
-	var pkg *ast.Package
-	for name, apkg := range pkgs {
-		if !strings.HasSuffix(name, "_test") {
-			pkg = apkg
-			break
-		}
-	}
-	if pkg == nil {
-		return nil, errors.New("no non-test package")
-	}
-	for filename := range pkg.Files {
-		if !strings.HasSuffix(filename, ".pb.go") {
-			return nil, fmt.Errorf("%s is not a .pb.go file", filename)
-		}
-	}
-	return pkg, nil
-}
-
-func generate(conf *config, pkg *ast.Package, fset *token.FileSet) (src []byte, err error) {
-	// Get information about all the types in the proto package.
-	typeInfos, err := collectDecls(pkg)
-	if err != nil {
-		return nil, err
-	}
-
-	// Check that every configured type is present.
-	for protoName := range conf.Types {
-		if typeInfos[protoName] == nil {
-			return nil, fmt.Errorf("configured type %s does not exist in package", protoName)
-		}
-	}
-
-	// Consult the config to determine which types to omit.
-	// If a type isn't matched by a glob in the OmitTypes list, it is output.
-	// If a type is matched, but it also has a config, it is still output.
-	var toWrite []*typeInfo
-	for name, ti := range typeInfos {
-		if !ast.IsExported(name) {
-			continue
-		}
-		omit, err := sliceAnyError(conf.OmitTypes, func(glob string) (bool, error) {
-			return path.Match(glob, name)
-		})
-		if err != nil {
-			return nil, err
-		}
-		if !omit || conf.Types[name] != nil {
-			toWrite = append(toWrite, ti)
-		}
-	}
-
-	// Fill in the configured type names, which we need to do the rest of the work.
-	for _, ti := range toWrite {
-		if tc := conf.Types[ti.protoName]; tc != nil && tc.Name != "" {
-			ti.veneerName = tc.Name
-		}
-	}
-
-	// Sort for determinism.
-	sort.Slice(toWrite, func(i, j int) bool {
-		return toWrite[i].veneerName < toWrite[j].veneerName
-	})
-
-	// Process and configure all the types we care about.
-	// Even if there is no config for a type, there is still work to do.
-	for _, ti := range toWrite {
-		if err := processType(ti, conf.Types[ti.protoName], typeInfos); err != nil {
-			return nil, err
-		}
-	}
-
-	converters, err := buildConverterMap(toWrite, conf)
-	if err != nil {
-		return nil, err
-	}
-
-	// Use the converters map to give every field a converter.
-	for _, ti := range toWrite {
-		for _, f := range ti.fields {
-			f.converter, err = makeConverter(f.af.Type, f.protoType, converters)
-			if err != nil {
-				return nil, fmt.Errorf("%s.%s: %w", ti.protoName, f.protoName, err)
-			}
-		}
-	}
-
-	// Write the generated code.
-	return write(toWrite, conf, fset)
-}
-
-// buildConverterMap builds a map from veneer name to a converter, which writes code that converts between the proto and veneer.
-// This is used for fields when generating conversion functions.
-func buildConverterMap(typeInfos []*typeInfo, conf *config) (map[string]converter, error) {
-	converters := map[string]converter{}
-	// Build a converter for each proto type.
-	for _, ti := range typeInfos {
-		var conv converter
-		// Custom converters on the type take precedence.
-		if tc := conf.Types[ti.protoName]; tc != nil && tc.ConvertToFrom != "" {
-			c, err := parseCustomConverter(ti.veneerName, tc.ConvertToFrom)
-			if err != nil {
-				return nil, err
-			}
-			conv = c
-		} else {
-			switch ti.spec.Type.(type) {
-			case *ast.StructType:
-				conv = protoConverter{veneerName: ti.veneerName}
-			case *ast.Ident:
-				conv = enumConverter{protoName: ti.protoName, veneerName: ti.veneerName}
-			default:
-				conv = identityConverter{}
-			}
-		}
-		converters[ti.veneerName] = conv
-	}
-
-	// Add converters for used external types to the map.
-	for _, et := range externalTypes {
-		if et.used {
-			converters[et.qualifiedName] = customConverter{et.convertTo, et.convertFrom}
-		}
-	}
-
-	// Add custom converters to the map.
-	// These differ from custom converters on the proto types (a few lines above here)
-	// because they are keyed by veneer type, not proto type.
-	// That can matter when the proto type is omitted but there is a corresponding
-	// veneer type.
-	for key, value := range conf.Converters {
-		c, err := parseCustomConverter(key, value)
-		if err != nil {
-			return nil, err
-		}
-		converters[key] = c
-	}
-	return converters, nil
-}
-
-func parseCustomConverter(name, value string) (converter, error) {
-	toFunc, fromFunc, ok := strings.Cut(value, ",")
-	toFunc = strings.TrimSpace(toFunc)
-	fromFunc = strings.TrimSpace(fromFunc)
-	if !ok || toFunc == "" || fromFunc == "" {
-		return nil, fmt.Errorf(`%s: ConvertToFrom = %q, want "toFunc, fromFunc"`, name, value)
-	}
-	return customConverter{toFunc, fromFunc}, nil
-}
-
-// makeConverter constructs a converter for the given type. Not every type is in the map: this
-// function puts together converters for types like pointers, slices and maps, as well as
-// named types.
-func makeConverter(veneerType, protoType ast.Expr, converters map[string]converter) (converter, error) {
-	if c, ok := converters[typeString(veneerType)]; ok {
-		return c, nil
-	}
-	// If there is no converter for this type, look for a converter for a part of the type.
-	switch t := veneerType.(type) {
-	case *ast.Ident:
-		// Handle the case where the veneer type is the dereference of the proto type.
-		if se, ok := protoType.(*ast.StarExpr); ok {
-			if identName(se.X) != t.Name {
-				return nil, fmt.Errorf("veneer type %s does not match dereferenced proto type %s", t.Name, identName(se.X))
-			}
-			return derefConverter{}, nil
-		}
-		return identityConverter{}, nil
-	case *ast.StarExpr:
-		return makeConverter(t.X, protoType.(*ast.StarExpr).X, converters)
-	case *ast.ArrayType:
-		eltc, err := makeConverter(t.Elt, protoType.(*ast.ArrayType).Elt, converters)
-		if err != nil {
-			return nil, err
-		}
-		return sliceConverter{eltc}, nil
-	case *ast.MapType:
-		// Assume the key types are the same.
-		vc, err := makeConverter(t.Value, protoType.(*ast.MapType).Value, converters)
-		if err != nil {
-			return nil, err
-		}
-		return mapConverter{vc}, nil
-	default:
-		return identityConverter{}, nil
-	}
-}
-
-// A typeInfo holds information about a named type.
-type typeInfo struct {
-	// These fields are collected from the proto package.
-	protoName string        // name of type in the proto package
-	spec      *ast.TypeSpec // the spec for the type, which will be modified
-	decl      *ast.GenDecl  // the decl holding the spec; not sure we need this
-	values    *ast.GenDecl  // the list of values for an enum
-
-	// These fields are added later.
-	veneerName string       // may be provided by config; else same as protoName
-	fields     []*fieldInfo // for structs
-	valueNames []string     // to generate String functions
-}
-
-// A fieldInfo holds information about a struct field.
-type fieldInfo struct {
-	protoType             ast.Expr
-	af                    *ast.Field
-	protoName, veneerName string
-	converter             converter
-}
-
-// collectDecls collects declaration information from a package.
-// It returns information about every named type in the package in a map
-// keyed by the type's name.
-func collectDecls(pkg *ast.Package) (map[string]*typeInfo, error) {
-	typeInfos := map[string]*typeInfo{} // key is proto name
-
-	getInfo := func(name string) *typeInfo {
-		if info, ok := typeInfos[name]; ok {
-			return info
-		}
-		info := &typeInfo{protoName: name, veneerName: name}
-		typeInfos[name] = info
-		return info
-	}
-
-	for _, file := range pkg.Files {
-		for _, decl := range file.Decls {
-			if gd, ok := decl.(*ast.GenDecl); ok {
-				switch gd.Tok {
-				case token.TYPE:
-					if len(gd.Specs) != 1 {
-						return nil, errors.New("multiple TypeSpecs in a GenDecl not supported")
-					}
-					ts := gd.Specs[0].(*ast.TypeSpec)
-					info := getInfo(ts.Name.Name)
-					info.spec = ts
-					info.decl = gd
-
-				case token.CONST:
-					// Assume consts for an enum type are grouped together, and every one has a type.
-					// That's what the proto compiler generates.
-					vs0 := gd.Specs[0].(*ast.ValueSpec)
-					if len(vs0.Names) != 1 || len(vs0.Values) != 1 {
-						return nil, errors.New("multiple names/values not supported")
-					}
-
-					protoName := identName(vs0.Type)
-					if protoName == "" {
-						continue
-					}
-					for _, s := range gd.Specs {
-						vs := s.(*ast.ValueSpec)
-						if identName(vs.Type) != protoName {
-							return nil, fmt.Errorf("%s: not all same type", protoName)
-						}
-					}
-					info := getInfo(protoName)
-					info.values = gd
-				}
-			}
-		}
-	}
-	return typeInfos, nil
-}
-
-// processType processes a single type, modifying the AST.
-// If it's an enum, just change its name.
-// If it's a struct, modify its name and fields.
-func processType(ti *typeInfo, tconf *typeConfig, typeInfos map[string]*typeInfo) error {
-	ti.spec.Name.Name = ti.veneerName
-	switch t := ti.spec.Type.(type) {
-	case *ast.StructType:
-		// Check that all configured fields are present.
-		exportedFields := map[string]bool{}
-		for _, f := range t.Fields.List {
-			if len(f.Names) > 1 {
-				return fmt.Errorf("%s: multiple names in one field spec not supported: %v", ti.protoName, f.Names)
-			}
-			if f.Names[0].IsExported() {
-				exportedFields[f.Names[0].Name] = true
-			}
-		}
-		if tconf != nil {
-			for name := range tconf.Fields {
-				if !exportedFields[name] {
-					return fmt.Errorf("%s: configured field %s is not present", ti.protoName, name)
-				}
-			}
-		}
-		// Process the fields.
-		fs := t.Fields.List
-		t.Fields.List = t.Fields.List[:0]
-		for _, f := range fs {
-			fi, err := processField(f, tconf, typeInfos)
-			if err != nil {
-				return err
-			}
-			if fi != nil {
-				t.Fields.List = append(t.Fields.List, f)
-				ti.fields = append(ti.fields, fi)
-			}
-		}
-	case *ast.Ident:
-		// Enum type. Nothing else to do with the type itself; but see processEnumValues.
-	default:
-		return fmt.Errorf("unknown type: %+v: protoName=%s", ti.spec, ti.protoName)
-	}
-	processDoc(ti.decl, ti.protoName, tconf)
-	if ti.values != nil {
-		ti.valueNames = processEnumValues(ti.values, tconf)
-	}
-	return nil
-}
-
-// processField processes a struct field.
-func processField(af *ast.Field, tc *typeConfig, typeInfos map[string]*typeInfo) (*fieldInfo, error) {
-	id := af.Names[0]
-	if !id.IsExported() {
-		return nil, nil
-	}
-	fi := &fieldInfo{
-		protoType:  af.Type,
-		af:         af,
-		protoName:  id.Name,
-		veneerName: id.Name,
-	}
-	if tc != nil {
-		if fc, ok := tc.Fields[id.Name]; ok {
-			if fc.Omit {
-				return nil, nil
-			}
-			if fc.Name != "" {
-				id.Name = fc.Name
-				fi.veneerName = fc.Name
-			}
-			if fc.Type != "" {
-				expr, err := parser.ParseExpr(fc.Type)
-				if err != nil {
-					return nil, err
-				}
-				af.Type = expr
-			}
-		}
-	}
-	af.Type = veneerType(af.Type, typeInfos)
-	af.Tag = nil
-	return fi, nil
-}
-
-// veneerType returns a type expression for the veneer type corresponding to the given proto type.
-func veneerType(protoType ast.Expr, typeInfos map[string]*typeInfo) ast.Expr {
-	var wtype func(ast.Expr) ast.Expr
-	wtype = func(protoType ast.Expr) ast.Expr {
-		if et := protoTypeToExternalType[typeString(protoType)]; et != nil {
-			et.used = true
-			return et.typeExpr
-		}
-		switch t := protoType.(type) {
-		case *ast.Ident:
-			if ti := typeInfos[t.Name]; ti != nil {
-				wt := *t
-				wt.Name = ti.veneerName
-				return &wt
-			}
-		case *ast.ParenExpr:
-			wt := *t
-			wt.X = wtype(wt.X)
-			return &wt
-
-		case *ast.StarExpr:
-			wt := *t
-			wt.X = wtype(wt.X)
-			return &wt
-
-		case *ast.ArrayType:
-			wt := *t
-			wt.Elt = wtype(wt.Elt)
-			return &wt
-		}
-		return protoType
-	}
-
-	return wtype(protoType)
-}
-
-// processEnumValues processes enum values.
-// The proto compiler puts all the values for an enum in one GenDecl,
-// and there are no other values in that GenDecl.
-func processEnumValues(d *ast.GenDecl, tc *typeConfig) []string {
-	var valueNames []string
-	for _, s := range d.Specs {
-		vs := s.(*ast.ValueSpec)
-		id := vs.Names[0]
-		protoName := id.Name
-		veneerName := veneerValueName(id.Name, tc)
-		valueNames = append(valueNames, veneerName)
-		id.Name = veneerName
-
-		if tc != nil {
-			vs.Type.(*ast.Ident).Name = tc.Name
-		}
-		modifyCommentGroup(vs.Doc, protoName, veneerName, "means", "")
-	}
-	return valueNames
-}
-
-// veneerValueName returns an idiomatic Go name for a proto enum value.
-func veneerValueName(protoValueName string, tc *typeConfig) string {
-	if tc == nil {
-		return protoValueName
-	}
-	if nn, ok := tc.ValueNames[protoValueName]; ok {
-		return nn
-	}
-	name := strings.TrimPrefix(protoValueName, tc.ProtoPrefix)
-	// Some values have the type name in upper snake case after the prefix.
-	// Example:
-	//    proto type: FinishReason
-	//    prefix: Candidate_
-	//    value:  Candidate_FINISH_REASON_UNSPECIFIED
-	prefix := camelToUpperSnakeCase(tc.Name) + "_"
-	name = strings.TrimPrefix(name, prefix)
-	return tc.VeneerPrefix + snakeToCamelCase(name)
-}
-
-func processDoc(gd *ast.GenDecl, protoName string, tc *typeConfig) {
-	doc := ""
-	verb := ""
-	if tc != nil {
-		doc = tc.Doc
-		verb = tc.DocVerb
-	}
-
-	spec := gd.Specs[0]
-	var name string
-	switch spec := spec.(type) {
-	case *ast.TypeSpec:
-		name = spec.Name.Name
-	case *ast.ValueSpec:
-		name = spec.Names[0].Name
-	default:
-		panic("bad spec")
-	}
-	if tc != nil && name != tc.Name {
-		panic(fmt.Errorf("GenDecl name is %q, config name is %q", name, tc.Name))
-	}
-	modifyCommentGroup(gd.Doc, protoName, name, verb, doc)
-}
-
-func modifyCommentGroup(cg *ast.CommentGroup, protoName, veneerName, verb, doc string) {
-	if cg == nil {
-		return
-	}
-	if len(cg.List) == 0 {
-		return
-	}
-	c := cg.List[0]
-	c.Text = "// " + adjustDoc(strings.TrimPrefix(c.Text, "// "), protoName, veneerName, verb, doc)
-}
-
-// adjustDoc takes a doc string with initial comment characters and whitespace removed, and returns
-// a replacement that uses the given veneer name, verb and new doc string.
-func adjustDoc(origDoc, protoName, veneerName, verb, newDoc string) string {
-	// if newDoc is non-empty, completely replace the existing doc.
-	if newDoc != "" {
-		return veneerName + " " + newDoc
-	}
-	// If the doc string starts with the proto name, just replace it with the
-	// veneer name. We can't do anything about the verb because we don't know
-	// where it is in the original doc string. (I guess we could assume it's the
-	// next word, but that might not always work.)
-	if strings.HasPrefix(origDoc, protoName+" ") {
-		return veneerName + origDoc[len(protoName):]
-	}
-
-	// Lowercase the first letter of the given doc if it's not part of an acronym.
-	runes := []rune(origDoc)
-	// It shouldn't be possible for the original doc string to be empty,
-	// but check just in case to avoid panics.
-	if len(runes) == 0 {
-		return origDoc
-	}
-	// Heuristic: an acronym begins with two consecutive uppercase letters.
-	if unicode.IsUpper(runes[0]) && (len(runes) == 1 || !unicode.IsUpper(runes[1])) {
-		runes[0] = unicode.ToLower(runes[0])
-		origDoc = string(runes)
-	}
-
-	if verb == "" {
-		verb = "is"
-	}
-	return fmt.Sprintf("%s %s %s", veneerName, verb, origDoc)
-}
-
-////////////////////////////////////////////////////////////////
-
-const licenseFormat = `// Copyright %d Google LLC
-//
-// 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.
-`
-
-func write(typeInfos []*typeInfo, conf *config, fset *token.FileSet) ([]byte, error) {
-	var buf bytes.Buffer
-	pr := func(format string, args ...any) { fmt.Fprintf(&buf, format, args...) }
-	prn := func(format string, args ...any) {
-		pr(format, args...)
-		pr("\n")
-	}
-	// Top of file.
-	pr(licenseFormat, time.Now().Year())
-	prn("")
-	pr("// This file was generated by protoveneer. DO NOT EDIT.\n\n")
-	pr("package %s\n\n", conf.Package)
-	prn("import (")
-	prn(`    "fmt"`)
-	pr("\n")
-	prn(`    pb "%s"`, conf.ProtoImportPath)
-	if conf.SupportImportPath == "" {
-		return nil, errors.New("missing supportImportPath in config")
-	}
-	prn(`    "%s"`, conf.SupportImportPath)
-	for _, et := range externalTypes {
-		if et.used && et.importPath != "" {
-			prn(`    "%s"`, et.importPath)
-		}
-	}
-	pr(")\n\n")
-
-	// Types.
-	for _, ti := range typeInfos {
-		for _, decl := range []*ast.GenDecl{ti.decl, ti.values} {
-			if decl != nil {
-				data, err := formatDecl(fset, decl)
-				if err != nil {
-					return nil, err
-				}
-				buf.Write(data)
-				prn("")
-			}
-		}
-		if ti.valueNames != nil {
-			if err := generateEnumStringMethod(&buf, ti.veneerName, ti.valueNames); err != nil {
-				return nil, err
-			}
-		}
-		if _, ok := ti.spec.Type.(*ast.StructType); ok {
-			ti.generateConversionMethods(pr)
-		}
-	}
-
-	return buf.Bytes(), nil
-}
-
-func formatDecl(fset *token.FileSet, gd *ast.GenDecl) ([]byte, error) {
-	var buf bytes.Buffer
-	if err := format.Node(&buf, fset, gd); err != nil {
-		return nil, err
-	}
-	// Remove blank lines that result from deleting unexported struct fields.
-	return bytes.ReplaceAll(buf.Bytes(), []byte("\n\n"), []byte("\n")), nil
-}
-
-////////////////////////////////////////////////////////////////
-
-var stringMethodTemplate = template.Must(template.New("").Parse(`
-	var namesFor{{.Type}} = map[{{.Type}}]string {
-		{{- range .Values}}
-			{{.}}: "{{.}}",
-		{{- end}}
-	}
-
-	func (v {{.Type}}) String() string {
-		if n, ok := namesFor{{.Type}}[v]; ok {
-			return n
-		}
-		return fmt.Sprintf("{{.Type}}(%d)", v)
-	}
-`))
-
-func generateEnumStringMethod(w io.Writer, typeName string, valueNames []string) error {
-	return stringMethodTemplate.Execute(w, struct {
-		Type   string
-		Values []string
-	}{typeName, valueNames})
-}
-
-func (ti *typeInfo) generateConversionMethods(pr func(string, ...any)) {
-	ti.generateToProto(pr)
-	pr("\n")
-	ti.generateFromProto(pr)
-}
-
-func (ti *typeInfo) generateToProto(pr func(string, ...any)) {
-	pr("func (v *%s) toProto() *pb.%s {\n", ti.veneerName, ti.protoName)
-	pr("  if v == nil { return nil }\n")
-	pr("  return &pb.%s{\n", ti.protoName)
-	for _, f := range ti.fields {
-		pr("        %s: %s,\n", f.protoName, f.converter.genTo("v."+f.veneerName))
-	}
-	pr("    }\n")
-	pr("}\n")
-}
-
-func (ti *typeInfo) generateFromProto(pr func(string, ...any)) {
-	pr("func (%s) fromProto(p *pb.%s) *%[1]s {\n", ti.veneerName, ti.protoName)
-	pr("  if p == nil { return nil }\n")
-	pr("  return &%s{\n", ti.veneerName)
-	for _, f := range ti.fields {
-		pr("        %s: %s,\n", f.veneerName, f.converter.genFrom("p."+f.protoName))
-	}
-	pr("    }\n")
-	pr("}\n")
-}
-
-////////////////////////////////////////////////////////////////
-
-// externalType holds information about a type that is not part of the proto package.
-type externalType struct {
-	qualifiedName string
-	replaces      string
-	importPath    string
-	convertTo     string
-	convertFrom   string
-
-	typeExpr ast.Expr
-	used     bool
-}
-
-var externalTypes = []*externalType{
-	{
-		qualifiedName: "civil.Date",
-		replaces:      "*date.Date",
-		importPath:    "cloud.google.com/go/civil",
-		convertTo:     "support.CivilDateToProto",
-		convertFrom:   "support.CivilDateFromProto",
-	},
-	{
-		qualifiedName: "map[string]any",
-		replaces:      "*structpb.Struct",
-		convertTo:     "support.MapToStructPB",
-		convertFrom:   "support.MapFromStructPB",
-	},
-}
-
-var protoTypeToExternalType = map[string]*externalType{}
-
-func init() {
-	var err error
-	for _, et := range externalTypes {
-		et.typeExpr, err = parser.ParseExpr(et.qualifiedName)
-		if err != nil {
-			panic(err)
-		}
-		protoTypeToExternalType[et.replaces] = et
-	}
-}
-
-////////////////////////////////////////////////////////////////
-
-var emptyFileSet = token.NewFileSet()
-
-// typeString produces a string for a type expression.
-func typeString(t ast.Expr) string {
-	var buf bytes.Buffer
-	err := format.Node(&buf, emptyFileSet, t)
-	if err != nil {
-		panic(err)
-	}
-	return buf.String()
-}
-
-func identName(x any) string {
-	id, ok := x.(*ast.Ident)
-	if !ok {
-		return ""
-	}
-	return id.Name
-}
-
-func snakeToCamelCase(s string) string {
-	words := strings.Split(s, "_")
-	for i, w := range words {
-		if len(w) == 0 {
-			words[i] = w
-		} else {
-			words[i] = fmt.Sprintf("%c%s", unicode.ToUpper(rune(w[0])), strings.ToLower(w[1:]))
-		}
-	}
-	return strings.Join(words, "")
-}
-
-func camelToUpperSnakeCase(s string) string {
-	var res []rune
-	for i, r := range s {
-		if unicode.IsUpper(r) && i > 0 {
-			res = append(res, '_')
-		}
-		res = append(res, unicode.ToUpper(r))
-	}
-	return string(res)
-}
-
-func sliceAnyError[T any](s []T, f func(T) (bool, error)) (bool, error) {
-	for _, e := range s {
-		b, err := f(e)
-		if err != nil {
-			return false, err
-		}
-		if b {
-			return true, nil
-		}
-	}
-	return false, nil
-}
diff --git a/protoveneer/cmd/protoveneer/protoveneer_test.go b/protoveneer/cmd/protoveneer/protoveneer_test.go
deleted file mode 100644
index 75c7d9b..0000000
--- a/protoveneer/cmd/protoveneer/protoveneer_test.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2023 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package main
-
-import (
-	"context"
-	"flag"
-	"os"
-	"path/filepath"
-	"testing"
-
-	"github.com/google/go-cmp/cmp"
-)
-
-var (
-	update = flag.Bool("update", false, "update test goldens")
-	keep   = flag.Bool("keep", false, "do not remove generated files")
-)
-
-func TestGeneration(t *testing.T) {
-	ctx := context.Background()
-	entries, err := os.ReadDir("testdata")
-	if err != nil {
-		t.Fatal(err)
-	}
-	for _, e := range entries {
-		if e.IsDir() {
-			t.Run(e.Name(), func(t *testing.T) {
-				dir := filepath.Join("testdata", e.Name())
-				configFile := filepath.Join(dir, "config.yaml")
-				goldenFile := filepath.Join(dir, "golden")
-				outFile := filepath.Join(dir, e.Name()+"_veneer.gen.go")
-				if *keep {
-					t.Logf("keeping %s", outFile)
-				} else {
-					defer os.Remove(outFile)
-				}
-				if err := run(ctx, configFile, dir, dir); err != nil {
-					t.Fatal(err)
-				}
-				if *update {
-					if err := os.Remove(goldenFile); err != nil {
-						t.Fatal(err)
-					}
-					if err := os.Rename(outFile, goldenFile); err != nil {
-						t.Fatal(err)
-					}
-					t.Logf("updated golden")
-				} else {
-					if diff := diffFiles(goldenFile, outFile); diff != "" {
-						t.Errorf("diff (-want, +got):\n%s", diff)
-					}
-				}
-			})
-		}
-	}
-}
-
-func diffFiles(wantFile, gotFile string) string {
-	want, err := os.ReadFile(wantFile)
-	if err != nil {
-		return err.Error()
-	}
-	got, err := os.ReadFile(gotFile)
-	if err != nil {
-		return err.Error()
-	}
-	return cmp.Diff(string(want), string(got))
-}
-
-func TestCamelToUpperSnakeCase(t *testing.T) {
-	for _, test := range []struct {
-		in, want string
-	}{
-		{"foo", "FOO"},
-		{"fooBar", "FOO_BAR"},
-		{"aBC", "A_B_C"},
-		{"ABC", "A_B_C"},
-	} {
-		got := camelToUpperSnakeCase(test.in)
-		if got != test.want {
-			t.Errorf("%q: got %q, want %q", test.in, got, test.want)
-		}
-	}
-}
-
-func TestAdjustDoc(t *testing.T) {
-	const protoName = "PName"
-	const veneerName = "VName"
-	for i, test := range []struct {
-		origDoc string
-		verb    string
-		newDoc  string
-		want    string
-	}{
-		{
-			origDoc: "",
-			verb:    "foo",
-			newDoc:  "",
-			want:    "",
-		},
-		{
-			origDoc: "",
-			verb:    "",
-			newDoc:  "is new doc.",
-			want:    "VName is new doc.",
-		},
-		{
-			origDoc: "The harm category is dangerous content.",
-			verb:    "means",
-			want:    "VName means the harm category is dangerous content.",
-		},
-		{
-			origDoc: "URI for the file.",
-			verb:    "is the",
-			want:    "VName is the URI for the file.",
-		},
-		{
-			origDoc: "PName is a thing.",
-			newDoc:  "contains something else.",
-			want:    "VName contains something else.",
-		},
-		{
-			origDoc: "PName is a thing.",
-			verb:    "ignored",
-			want:    "VName is a thing.",
-		},
-	} {
-		got := adjustDoc(test.origDoc, protoName, veneerName, test.verb, test.newDoc)
-		if got != test.want {
-			t.Errorf("#%d: got %q, want %q", i, got, test.want)
-		}
-	}
-}
diff --git a/protoveneer/cmd/protoveneer/testdata/basic/basic.pb.go b/protoveneer/cmd/protoveneer/testdata/basic/basic.pb.go
deleted file mode 100755
index 25f0c75..0000000
--- a/protoveneer/cmd/protoveneer/testdata/basic/basic.pb.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2023 Google LLC
-//
-// 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 basic
-
-import (
-	_ "google.golang.org/genproto/googleapis/api/annotations"
-	date "google.golang.org/genproto/googleapis/type/date"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	"google.golang.org/protobuf/types/known/structpb"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// Harm categories that will block the content.
-type HarmCategory int32
-
-const (
-	// The harm category is unspecified.
-	HarmCategory_HARM_CATEGORY_UNSPECIFIED HarmCategory = 0
-	// The harm category is hate speech.
-	HarmCategory_HARM_CATEGORY_HATE_SPEECH HarmCategory = 1
-	// The harm category is dangerous content.
-	HarmCategory_HARM_CATEGORY_DANGEROUS_CONTENT HarmCategory = 2
-	// The harm category is harassment.
-	HarmCategory_HARM_CATEGORY_HARASSMENT HarmCategory = 3
-	// The harm category is sexually explicit content.
-	HarmCategory_HARM_CATEGORY_SEXUALLY_EXPLICIT HarmCategory = 4
-)
-
-// The reason why the model stopped generating tokens.
-// If empty, the model has not stopped generating the tokens.
-type Candidate_FinishReason int32
-
-const (
-	// The finish reason is unspecified.
-	Candidate_FINISH_REASON_UNSPECIFIED Candidate_FinishReason = 0
-	// Natural stop point of the model or provided stop sequence.
-	Candidate_STOP Candidate_FinishReason = 1
-	// The maximum number of tokens as specified in the request was reached.
-	Candidate_MAX_TOKENS Candidate_FinishReason = 2
-	// The token generation was stopped as the response was flagged for safety
-	// reasons. NOTE: When streaming the Candidate.content will be empty if
-	// content filters blocked the output.
-	Candidate_SAFETY Candidate_FinishReason = 3
-	// The token generation was stopped as the response was flagged for
-	// unauthorized citations.
-	Candidate_RECITATION Candidate_FinishReason = 4
-	// All other reasons that stopped the token generation
-	Candidate_OTHER Candidate_FinishReason = 5
-)
-
-// Raw media bytes.
-//
-// Text should not be sent as raw bytes, use the 'text' field.
-type Blob struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Required. The IANA standard MIME type of the source data.
-	MimeType string `protobuf:"bytes,1,opt,name=mime_type,json=mimeType,proto3" json:"mime_type,omitempty"`
-	// Required. Raw bytes for media formats.
-	Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
-}
-
-// Generation config.
-type GenerationConfig struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Optional. Controls the randomness of predictions.
-	Temperature *float32 `protobuf:"fixed32,1,opt,name=temperature,proto3,oneof" json:"temperature,omitempty"`
-	// Optional. Number of candidates to generate.
-	CandidateCount *int32 `protobuf:"varint,4,opt,name=candidate_count,json=candidateCount,proto3,oneof" json:"candidate_count,omitempty"`
-	// Optional. Stop sequences.
-	StopSequences []string `protobuf:"bytes,6,rep,name=stop_sequences,json=stopSequences,proto3" json:"stop_sequences,omitempty"`
-	HarmCat       HarmCategory
-	FinishReason  Candidate_FinishReason
-	CitMet        *CitationMetadata
-}
-
-// A collection of source attributions for a piece of content.
-type CitationMetadata struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Output only. List of citations.
-	Citations []*Citation `protobuf:"bytes,1,rep,name=citations,proto3" json:"citations,omitempty"`
-	CitMap    map[string]*Citation
-}
-
-// Source attributions for content.
-type Citation struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Output only. Url reference of the attribution.
-	Uri string `protobuf:"bytes,3,opt,name=uri,proto3" json:"uri,omitempty"`
-	// Output only. Publication date of the attribution.
-	PublicationDate *date.Date `protobuf:"bytes,6,opt,name=publication_date,json=publicationDate,proto3" json:"publication_date,omitempty"`
-	Struct          *structpb.Struct
-}
diff --git a/protoveneer/cmd/protoveneer/testdata/basic/config.yaml b/protoveneer/cmd/protoveneer/testdata/basic/config.yaml
deleted file mode 100644
index 9a54cbe..0000000
--- a/protoveneer/cmd/protoveneer/testdata/basic/config.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright 2023 Google LLC
-#
-# 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: basic
-protoImportPath: example.com/basic
-supportImportPath: example.com/protoveneer/support
-
-types:
-    HarmCategory:
-      protoPrefix: HarmCategory_HARM_CATEGORY_
-      docVerb: specifies
-
-    Candidate_FinishReason:
-      name: FinishReason
-      protoPrefix: Candidate_
-
-    Blob:
-      fields:
-        MimeType:
-          name: MIMEType
-      docVerb: contains
-
-    GenerationConfig:
-      fields:
-        Temperature:
-          type: float32
-        CandidateCount:
-          type: int32
-
-    Citation:
-      docVerb: contains
-      fields:
-        Uri:
-          name: URI
diff --git a/protoveneer/cmd/protoveneer/testdata/basic/golden b/protoveneer/cmd/protoveneer/testdata/basic/golden
deleted file mode 100644
index ec4b158..0000000
--- a/protoveneer/cmd/protoveneer/testdata/basic/golden
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2023 Google LLC
-//
-// 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 file was generated by protoveneer. DO NOT EDIT.
-
-package basic
-
-import (
-	"fmt"
-
-	"cloud.google.com/go/civil"
-	pb "example.com/basic"
-	"example.com/protoveneer/support"
-)
-
-// Blob contains raw media bytes.
-//
-// Text should not be sent as raw bytes, use the 'text' field.
-type Blob struct {
-	// Required. The IANA standard MIME type of the source data.
-	MIMEType string
-	// Required. Raw bytes for media formats.
-	Data []byte
-}
-
-func (v *Blob) toProto() *pb.Blob {
-	if v == nil {
-		return nil
-	}
-	return &pb.Blob{
-		MimeType: v.MIMEType,
-		Data:     v.Data,
-	}
-}
-
-func (Blob) fromProto(p *pb.Blob) *Blob {
-	if p == nil {
-		return nil
-	}
-	return &Blob{
-		MIMEType: p.MimeType,
-		Data:     p.Data,
-	}
-}
-
-// Citation contains source attributions for content.
-type Citation struct {
-	// Output only. Url reference of the attribution.
-	URI string
-	// Output only. Publication date of the attribution.
-	PublicationDate civil.Date
-	Struct          map[string]any
-}
-
-func (v *Citation) toProto() *pb.Citation {
-	if v == nil {
-		return nil
-	}
-	return &pb.Citation{
-		Uri:             v.URI,
-		PublicationDate: support.CivilDateToProto(v.PublicationDate),
-		Struct:          support.MapToStructPB(v.Struct),
-	}
-}
-
-func (Citation) fromProto(p *pb.Citation) *Citation {
-	if p == nil {
-		return nil
-	}
-	return &Citation{
-		URI:             p.Uri,
-		PublicationDate: support.CivilDateFromProto(p.PublicationDate),
-		Struct:          support.MapFromStructPB(p.Struct),
-	}
-}
-
-// CitationMetadata is a collection of source attributions for a piece of content.
-type CitationMetadata struct {
-	// Output only. List of citations.
-	Citations []*Citation
-	CitMap    map[string]*Citation
-}
-
-func (v *CitationMetadata) toProto() *pb.CitationMetadata {
-	if v == nil {
-		return nil
-	}
-	return &pb.CitationMetadata{
-		Citations: support.TransformSlice(v.Citations, (*Citation).toProto),
-		CitMap:    support.TransformMapValues(v.CitMap, (*Citation).toProto),
-	}
-}
-
-func (CitationMetadata) fromProto(p *pb.CitationMetadata) *CitationMetadata {
-	if p == nil {
-		return nil
-	}
-	return &CitationMetadata{
-		Citations: support.TransformSlice(p.Citations, (Citation{}).fromProto),
-		CitMap:    support.TransformMapValues(p.CitMap, (Citation{}).fromProto),
-	}
-}
-
-// FinishReason is the reason why the model stopped generating tokens.
-// If empty, the model has not stopped generating the tokens.
-type FinishReason int32
-
-const (
-	// FinishReasonUnspecified means the finish reason is unspecified.
-	FinishReasonUnspecified FinishReason = 0
-	// FinishReasonStop means natural stop point of the model or provided stop sequence.
-	FinishReasonStop FinishReason = 1
-	// FinishReasonMaxTokens means the maximum number of tokens as specified in the request was reached.
-	FinishReasonMaxTokens FinishReason = 2
-	// FinishReasonSafety means the token generation was stopped as the response was flagged for safety
-	// reasons. NOTE: When streaming the Candidate.content will be empty if
-	// content filters blocked the output.
-	FinishReasonSafety FinishReason = 3
-	// FinishReasonRecitation means the token generation was stopped as the response was flagged for
-	// unauthorized citations.
-	FinishReasonRecitation FinishReason = 4
-	// FinishReasonOther means all other reasons that stopped the token generation
-	FinishReasonOther FinishReason = 5
-)
-
-var namesForFinishReason = map[FinishReason]string{
-	FinishReasonUnspecified: "FinishReasonUnspecified",
-	FinishReasonStop:        "FinishReasonStop",
-	FinishReasonMaxTokens:   "FinishReasonMaxTokens",
-	FinishReasonSafety:      "FinishReasonSafety",
-	FinishReasonRecitation:  "FinishReasonRecitation",
-	FinishReasonOther:       "FinishReasonOther",
-}
-
-func (v FinishReason) String() string {
-	if n, ok := namesForFinishReason[v]; ok {
-		return n
-	}
-	return fmt.Sprintf("FinishReason(%d)", v)
-}
-
-// GenerationConfig is generation config.
-type GenerationConfig struct {
-	// Optional. Controls the randomness of predictions.
-	Temperature float32
-	// Optional. Number of candidates to generate.
-	CandidateCount int32
-	// Optional. Stop sequences.
-	StopSequences []string
-	HarmCat       HarmCategory
-	FinishReason  FinishReason
-	CitMet        *CitationMetadata
-}
-
-func (v *GenerationConfig) toProto() *pb.GenerationConfig {
-	if v == nil {
-		return nil
-	}
-	return &pb.GenerationConfig{
-		Temperature:    support.AddrOrNil(v.Temperature),
-		CandidateCount: support.AddrOrNil(v.CandidateCount),
-		StopSequences:  v.StopSequences,
-		HarmCat:        pb.HarmCategory(v.HarmCat),
-		FinishReason:   pb.Candidate_FinishReason(v.FinishReason),
-		CitMet:         v.CitMet.toProto(),
-	}
-}
-
-func (GenerationConfig) fromProto(p *pb.GenerationConfig) *GenerationConfig {
-	if p == nil {
-		return nil
-	}
-	return &GenerationConfig{
-		Temperature:    support.DerefOrZero(p.Temperature),
-		CandidateCount: support.DerefOrZero(p.CandidateCount),
-		StopSequences:  p.StopSequences,
-		HarmCat:        HarmCategory(p.HarmCat),
-		FinishReason:   FinishReason(p.FinishReason),
-		CitMet:         (CitationMetadata{}).fromProto(p.CitMet),
-	}
-}
-
-// HarmCategory specifies harm categories that will block the content.
-type HarmCategory int32
-
-const (
-	// HarmCategoryUnspecified means the harm category is unspecified.
-	HarmCategoryUnspecified HarmCategory = 0
-	// HarmCategoryHateSpeech means the harm category is hate speech.
-	HarmCategoryHateSpeech HarmCategory = 1
-	// HarmCategoryDangerousContent means the harm category is dangerous content.
-	HarmCategoryDangerousContent HarmCategory = 2
-	// HarmCategoryHarassment means the harm category is harassment.
-	HarmCategoryHarassment HarmCategory = 3
-	// HarmCategorySexuallyExplicit means the harm category is sexually explicit content.
-	HarmCategorySexuallyExplicit HarmCategory = 4
-)
-
-var namesForHarmCategory = map[HarmCategory]string{
-	HarmCategoryUnspecified:      "HarmCategoryUnspecified",
-	HarmCategoryHateSpeech:       "HarmCategoryHateSpeech",
-	HarmCategoryDangerousContent: "HarmCategoryDangerousContent",
-	HarmCategoryHarassment:       "HarmCategoryHarassment",
-	HarmCategorySexuallyExplicit: "HarmCategorySexuallyExplicit",
-}
-
-func (v HarmCategory) String() string {
-	if n, ok := namesForHarmCategory[v]; ok {
-		return n
-	}
-	return fmt.Sprintf("HarmCategory(%d)", v)
-}
diff --git a/protoveneer/go.mod b/protoveneer/go.mod
deleted file mode 100644
index 03579fb..0000000
--- a/protoveneer/go.mod
+++ /dev/null
@@ -1,11 +0,0 @@
-module golang.org/x/exp/protoveneer
-
-go 1.21
-
-require (
-	cloud.google.com/go v0.111.0
-	github.com/google/go-cmp v0.6.0
-	google.golang.org/genproto v0.0.0-20231212172506-995d672761c0
-	google.golang.org/protobuf v1.31.0
-	gopkg.in/yaml.v3 v3.0.1
-)
diff --git a/protoveneer/go.sum b/protoveneer/go.sum
deleted file mode 100644
index b6f598c..0000000
--- a/protoveneer/go.sum
+++ /dev/null
@@ -1,16 +0,0 @@
-cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM=
-cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos=
-google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
-google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/protoveneer/support/support.go b/protoveneer/support/support.go
deleted file mode 100644
index 5e74f3b..0000000
--- a/protoveneer/support/support.go
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2023 Google LLC
-//
-// 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 support provides support functions for protoveneer.
-package support
-
-import (
-	"fmt"
-	"time"
-
-	"cloud.google.com/go/civil"
-	"google.golang.org/genproto/googleapis/type/date"
-	"google.golang.org/protobuf/types/known/structpb"
-)
-
-// TransformSlice applies f to each element of from and returns
-// a new slice with the results.
-func TransformSlice[From, To any](from []From, f func(From) To) []To {
-	if from == nil {
-		return nil
-	}
-	to := make([]To, len(from))
-	for i, e := range from {
-		to[i] = f(e)
-	}
-	return to
-}
-
-// TransformMapValues applies f to each value of from, returning a new map.
-// It does not change the keys.
-func TransformMapValues[K comparable, VFrom, VTo any](from map[K]VFrom, f func(VFrom) VTo) map[K]VTo {
-	if from == nil {
-		return nil
-	}
-	to := map[K]VTo{}
-	for k, v := range from {
-		to[k] = f(v)
-	}
-	return to
-}
-
-// AddrOrNil returns nil if x is the zero value for T,
-// or &x otherwise.
-func AddrOrNil[T comparable](x T) *T {
-	var z T
-	if x == z {
-		return nil
-	}
-	return &x
-}
-
-// DerefOrZero returns the zero value for T if x is nil,
-// or *x otherwise.
-func DerefOrZero[T any](x *T) T {
-	if x == nil {
-		var z T
-		return z
-	}
-	return *x
-}
-
-// CivilDateToProto converts a civil.Date to a date.Date.
-func CivilDateToProto(d civil.Date) *date.Date {
-	return &date.Date{
-		Year:  int32(d.Year),
-		Month: int32(d.Month),
-		Day:   int32(d.Day),
-	}
-}
-
-// CivilDateFromProto converts a date.Date to a civil.Date.
-func CivilDateFromProto(p *date.Date) civil.Date {
-	if p == nil {
-		return civil.Date{}
-	}
-	return civil.Date{
-		Year:  int(p.Year),
-		Month: time.Month(p.Month),
-		Day:   int(p.Day),
-	}
-}
-
-// MapToStructPB converts a map into a structpb.Struct.
-func MapToStructPB(m map[string]any) *structpb.Struct {
-	if m == nil {
-		return nil
-	}
-	s, err := structpb.NewStruct(m)
-	if err != nil {
-		panic(fmt.Errorf("support.MapToProto: %w", err))
-	}
-	return s
-}
-
-// MapFromStructPB converts a structpb.Struct to a map.
-func MapFromStructPB(p *structpb.Struct) map[string]any {
-	if p == nil {
-		return nil
-	}
-	return p.AsMap()
-}
diff --git a/protoveneer/support/support_test.go b/protoveneer/support/support_test.go
deleted file mode 100644
index c3def96..0000000
--- a/protoveneer/support/support_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2023 Google LLC
-//
-// 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 support
-
-import (
-	"reflect"
-	"strconv"
-	"testing"
-)
-
-func TestTransformMapValues(t *testing.T) {
-	var from map[string]int
-	got := TransformMapValues(from, strconv.Itoa)
-	if got != nil {
-		t.Fatalf("got %v, want nil", got)
-	}
-	from = map[string]int{"one": 1, "two": 2}
-	got = TransformMapValues(from, strconv.Itoa)
-	want := map[string]string{"one": "1", "two": "2"}
-	if !reflect.DeepEqual(got, want) {
-		t.Errorf("got %v, want %v", got, want)
-	}
-}