Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Unified Diff: tools/proto-gae/proto_gae.go

Issue 1625773002: Add tool to generate PropertyConverter implementations for proto messages. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: Fix nit, use bufio Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/proto-gae/README.md ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/proto-gae/proto_gae.go
diff --git a/tools/proto-gae/proto_gae.go b/tools/proto-gae/proto_gae.go
new file mode 100644
index 0000000000000000000000000000000000000000..6db06781b3e1ee3ee3bfcb39f3e37d7f40051e2d
--- /dev/null
+++ b/tools/proto-gae/proto_gae.go
@@ -0,0 +1,160 @@
+// Copyright 2015 The Chromium 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 (
+ "bufio"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "sort"
+ "strings"
+ "text/template"
+
+ "github.com/luci/luci-go/common/errors"
+ "github.com/luci/luci-go/common/flag/stringsetflag"
+)
+
+type app struct {
+ out io.Writer
+
+ packageName string
+ typeNames stringsetflag.Flag
+ outFile string
+}
+
+const help = `Usage of %s:
+
+%s is a go-generator program that generates PropertyConverter implementations
+for types produced by protoc. It can be used in a go generation file like:
+
+ //go:generate <protoc command>
+ //go:generate proto-gae -type MessageType -type OtherMessageType
+
+This will produce a new file which implements the ToProperty and FromProperty
+methods for the named types.
+
+Options:
+`
+
+func (a *app) parseArgs(fs *flag.FlagSet, args []string) error {
+ fs.SetOutput(a.out)
+ fs.Usage = func() {
+ fmt.Fprintf(a.out, help, args[0], args[0])
+ fs.PrintDefaults()
+ }
+
+ fs.Var(&a.typeNames, "type",
+ "A generated proto.Message type to generate stubs for (required, repeatable)")
+ fs.StringVar(&a.outFile, "out", "proto_gae.gen.go",
+ "The name of the output file")
+
+ if err := fs.Parse(args[1:]); err != nil {
+ return err
+ }
+ fail := errors.MultiError(nil)
+ if a.typeNames.Data == nil || a.typeNames.Data.Len() == 0 {
+ fail = append(fail, errors.New("must specify one or more -type"))
+ }
+ if !strings.HasSuffix(a.outFile, ".go") {
+ fail = append(fail, errors.New("-output must end with '.go'"))
+ }
+ if len(fail) > 0 {
+ for _, e := range fail {
+ fmt.Fprintln(a.out, "error:", e)
+ }
+ fmt.Fprintln(a.out)
+ fs.Usage()
+ return fail
+ }
+ return nil
+}
+
+var tmpl = template.Must(
+ template.New("main").Parse(`// AUTOGENERATED: Do not edit
+
+package {{index . "package"}}
+
+import (
+ "github.com/golang/protobuf/proto"
+
+ "github.com/luci/gae/service/datastore"
+){{range index . "types"}}
+
+var _ datastore.PropertyConverter = (*{{.}})(nil)
+
+// ToProperty implements datastore.PropertyConverter. It causes an embedded
+// '{{.}}' to serialize to an unindexed '[]byte' when used with the
+// "github.com/luci/gae" library.
+func (p *{{.}}) ToProperty() (prop datastore.Property, err error) {
+ data, err := proto.Marshal(p)
+ if err == nil {
+ prop.SetValue(data, datastore.NoIndex)
+ }
+ return
+}
+
+// FromProperty implements datastore.PropertyConverter. It parses a '[]byte'
+// into an embedded '{{.}}' when used with the "github.com/luci/gae" library.
+func (p *{{.}}) FromProperty(prop datastore.Property) error {
+ data, err := prop.Project(datastore.PTBytes)
+ if err != nil {
+ return err
+ }
+ return proto.Unmarshal(data.([]byte), p)
+}{{end}}
+`))
+
+func (a *app) writeTo(w io.Writer) error {
+ typeNames := a.typeNames.Data.ToSlice()
+ sort.Strings(typeNames)
+
+ return tmpl.Execute(w, map[string]interface{}{
+ "package": a.packageName,
+ "types": typeNames,
+ })
+}
+
+func (a *app) main() {
+ if err := a.parseArgs(flag.NewFlagSet(os.Args[0], flag.ContinueOnError), os.Args); err != nil {
+ os.Exit(1)
+ }
+ ofile, err := os.Create(a.outFile)
+ if err != nil {
+ fmt.Fprintf(a.out, "error: %s", err)
+ os.Exit(2)
+ }
+ closeFn := func(delete bool) {
+ if ofile != nil {
+ if err := ofile.Close(); err != nil {
+ fmt.Fprintf(a.out, "error while closing file: %s", err)
+ }
+ if delete {
+ if err := os.Remove(a.outFile); err != nil {
+ fmt.Fprintf(a.out, "failed to remove file!")
+ }
+ }
+ }
+ ofile = nil
+ }
+ defer closeFn(false)
+ buf := bufio.NewWriter(ofile)
+ err = a.writeTo(buf)
+ if err != nil {
+ fmt.Fprintf(a.out, "error while writing: %s", err)
+ closeFn(true)
+ os.Exit(3)
+ }
+ if err := buf.Flush(); err != nil {
+ fmt.Fprintf(a.out, "error while writing: %s", err)
+ closeFn(true)
+ os.Exit(4)
+ }
+}
+
+func main() {
+ (&app{out: os.Stderr, packageName: os.Getenv("GOPACKAGE")}).main()
+}
« no previous file with comments | « tools/proto-gae/README.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698