github.com/chrislusf/greenpack@v3.7.1-0.20170911073826-ad5bd10b7c47+incompatible/main.go (about) 1 // greenpack is a code generation tool for 2 // creating methods to serialize and de-serialize 3 // Go data structures to and from Greenpack (a 4 // schema-based serialization format that is derived 5 // from MessagePack2). 6 // 7 // This package is targeted at the `go generate` tool. 8 // To use it, include the following directive in a 9 // go source file with types requiring source generation: 10 // 11 // //go:generate greenpack 12 // 13 // The go generate tool should set the proper environment variables for 14 // the generator to execute without any command-line flags. However, the 15 // following options are supported, if you need them (See greenpack -h): 16 // 17 // $ greenpack -h 18 // 19 // Usage of greenpack: 20 // 21 // -fast-strings 22 // for speed when reading a string in a message that won't be 23 // reused, this flag means we'll use unsafe to cast the string 24 // header and avoid allocation. 25 // 26 // -file go generate 27 // input file (or directory); default is $GOFILE, which 28 // is set by the go generate command. 29 // 30 // -genid 31 // generate a fresh random greenSchemaId64 value to 32 // include in your Go source schema 33 // 34 // -io 35 // create Encode and Decode methods (default true) 36 // 37 // -marshal 38 // create Marshal and Unmarshal methods (default true) 39 // 40 // -method-prefix string 41 // (optional) prefix that will be pre-prended to 42 // the front of generated method names; useful when 43 // you need to avoid namespace collisions, but the 44 // generated tests will break/the msgp package 45 // interfaces won't be satisfied. 46 // 47 // -no-embedded-schema 48 // don't embed the schema in the generated files 49 // 50 // -no-structnames-onwire 51 // don't embed the name of the struct in the 52 // serialized greenpack. Skipping the embedded 53 // struct names saves time and space and matches 54 // what protocol buffers/thrift/capnproto/msgpack do. 55 // You must know the type on the wire you expect; 56 // or embed a type tag in one universal wrapper 57 // struct. Embedded struct names are a feature 58 // of Greenpack to help with dynamic language 59 // bindings. 60 // 61 // -o string 62 // output file (default is {input_file}_gen.go 63 // 64 // -schema-to-go string 65 // (standalone functionality) path to schema in msgpack2 66 // format; we will convert it to Go, write the Go on stdout, 67 // and exit immediately 68 // 69 // -tests 70 // create tests and benchmarks (default true) 71 // 72 // -unexported 73 // also process unexported types 74 // 75 // -write-schema string 76 // write schema header to this file; - for stdout 77 // 78 // 79 // For more information, please read README.md, and the wiki at github.com/glycerine/greenpack 80 // 81 package main 82 83 import ( 84 "flag" 85 "fmt" 86 "os" 87 "path/filepath" 88 "strings" 89 90 "github.com/glycerine/greenpack/cfg" 91 "github.com/glycerine/greenpack/gen" 92 "github.com/glycerine/greenpack/parse" 93 "github.com/glycerine/greenpack/printer" 94 ) 95 96 func main() { 97 myflags := flag.NewFlagSet("greenpack", flag.ExitOnError) 98 c := &cfg.GreenConfig{} 99 c.DefineFlags(myflags) 100 101 err := myflags.Parse(os.Args[1:]) 102 err = c.ValidateConfig() 103 if err != nil { 104 fmt.Printf("greenpack command line flag error: '%s'\n", err) 105 os.Exit(1) 106 } 107 108 if c.ShowVersion { 109 fmt.Println(GetCodeVersion(os.Args[0])) 110 os.Exit(0) 111 } 112 113 // GOFILE is set by go generate 114 if c.GoFile == "" { 115 c.GoFile = os.Getenv("GOFILE") 116 if c.GoFile == "" { 117 fmt.Println("No file to parse.") 118 os.Exit(1) 119 } 120 } 121 gen.SetFilename(c.GoFile) 122 123 var mode gen.Method 124 if c.Encode { 125 mode |= (gen.Encode | gen.Decode | gen.Size | gen.FieldsEmpty) 126 } 127 if c.Marshal { 128 mode |= (gen.Marshal | gen.Unmarshal | gen.Size | gen.FieldsEmpty) 129 } 130 if c.Tests { 131 mode |= gen.Test 132 } 133 134 if mode&^gen.Test == 0 { 135 fmt.Println("No methods to generate; -io=false && -marshal=false") 136 os.Exit(1) 137 } 138 139 if err := Run(mode, c); err != nil { 140 fmt.Println(err.Error()) 141 os.Exit(1) 142 } 143 } 144 145 // Run writes all methods using the associated file or path, e.g. 146 // 147 // err := msgp.Run("path/to/myfile.go", gen.Size|gen.Marshal|gen.Unmarshal|gen.Test, false) 148 // 149 func Run(mode gen.Method, c *cfg.GreenConfig) error { 150 if mode&^gen.Test == 0 { 151 return nil 152 } 153 fmt.Println("======== Greenpack Code Generator =======") 154 fmt.Printf(">>> Input: \"%s\"\n", c.GoFile) 155 var fs *parse.FileSet 156 var err error 157 //if c.NoLoad { 158 fs, err = parse.FileNoLoad(c) 159 //} else { 160 // fs, err = parse.File(c) 161 //} 162 if err != nil { 163 return err 164 } 165 166 if len(fs.Identities) == 0 { 167 fmt.Println("No types requiring code generation were found!") 168 return nil 169 } 170 171 return printer.PrintFile(newFilename(c.Out, c.GoFile, fs.Package), fs, mode, c, c.GoFile) 172 } 173 174 // picks a new file name based on input flags and input filename(s). 175 func newFilename(out, old, pkg string) string { 176 if out != "" { 177 if pre := strings.TrimPrefix(out, old); len(pre) > 0 && 178 !strings.HasSuffix(out, ".go") { 179 return filepath.Join(old, out) 180 } 181 return out 182 } 183 184 if fi, err := os.Stat(old); err == nil && fi.IsDir() { 185 old = filepath.Join(old, pkg) 186 } 187 // new file name is old file name + _gen.go 188 return strings.TrimSuffix(old, ".go") + "_gen.go" 189 } 190 191 func fileExists(name string) bool { 192 fi, err := os.Stat(name) 193 if err != nil { 194 return false 195 } 196 if fi.IsDir() { 197 return false 198 } 199 return true 200 }