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)
- }
-}