// msgp is a code generation tool for // creating methods to serialize and de-serialize // Go data structures to and from MessagePack. // // This package is targeted at the `go generate` tool. // To use it, include the following directive in a // go source file with types requiring source generation: // // //go:generate msgp // // The go generate tool should set the proper environment variables for // the generator to execute without any command-line flags. However, the // following options are supported, if you need them: // // -o = output file name (default is {input}_gen.go) // -file = input file name (or directory; default is $GOFILE, which is set by the `go generate` command) // -io = satisfy the `msgp.Decodable` and `msgp.Encodable` interfaces (default is true) // -marshal = satisfy the `msgp.Marshaler` and `msgp.Unmarshaler` interfaces (default is true) // -tests = generate tests and benchmarks (default is true) // // For more information, please read README.md, and the wiki at github.com/tinylib/msgp // package main import ( "flag" "fmt" "os" "path/filepath" "strings" "github.com/tinylib/msgp/gen" "github.com/tinylib/msgp/parse" "github.com/tinylib/msgp/printer" "github.com/ttacon/chalk" ) var ( out = flag.String("o", "", "output file") file = flag.String("file", "", "input file") encode = flag.Bool("io", true, "create Encode and Decode methods") marshal = flag.Bool("marshal", true, "create Marshal and Unmarshal methods") tests = flag.Bool("tests", true, "create tests and benchmarks") unexported = flag.Bool("unexported", false, "also process unexported types") ) func main() { flag.Parse() // GOFILE is set by go generate if *file == "" { *file = os.Getenv("GOFILE") if *file == "" { fmt.Println(chalk.Red.Color("No file to parse.")) os.Exit(1) } } var mode gen.Method if *encode { mode |= (gen.Encode | gen.Decode | gen.Size) } if *marshal { mode |= (gen.Marshal | gen.Unmarshal | gen.Size) } if *tests { mode |= gen.Test } if mode&^gen.Test == 0 { fmt.Println(chalk.Red.Color("No methods to generate; -io=false && -marshal=false")) os.Exit(1) } if err := Run(*file, mode, *unexported); err != nil { fmt.Println(chalk.Red.Color(err.Error())) os.Exit(1) } } // Run writes all methods using the associated file or path, e.g. // // err := msgp.Run("path/to/myfile.go", gen.Size|gen.Marshal|gen.Unmarshal|gen.Test, false) // func Run(gofile string, mode gen.Method, unexported bool) error { if mode&^gen.Test == 0 { return nil } fmt.Println(chalk.Magenta.Color("======== MessagePack Code Generator =======")) fmt.Printf(chalk.Magenta.Color(">>> Input: \"%s\"\n"), gofile) fs, err := parse.File(gofile, unexported) if err != nil { return err } if len(fs.Identities) == 0 { fmt.Println(chalk.Magenta.Color("No types requiring code generation were found!")) return nil } return printer.PrintFile(newFilename(gofile, fs.Package), fs, mode) } // picks a new file name based on input flags and input filename(s). func newFilename(old string, pkg string) string { if *out != "" { if pre := strings.TrimPrefix(*out, old); len(pre) > 0 && !strings.HasSuffix(*out, ".go") { return filepath.Join(old, *out) } return *out } if fi, err := os.Stat(old); err == nil && fi.IsDir() { old = filepath.Join(old, pkg) } // new file name is old file name + _gen.go return strings.TrimSuffix(old, ".go") + "_gen.go" }