func getFlatTypes(req *compiler.CodeGeneratorRequest, exported bool, out *FlatTypes) *FlatTypes { include := func(string) bool { return true } if exported { include = func(name string) bool { for _, n := range req.GetFileToGenerate() { if n == name { return true } } return false } } for _, pkg := range req.GetProtoFile() { if !include(pkg.GetName()) { continue } out = flatTypesForFile(pkg, out) } return out }
func main() { log.SetPrefix("pinktxt: ") log.SetFlags(0) var resp = new(compiler.CodeGeneratorResponse) defer func() { output, err := proto.Marshal(resp) if err != nil { log.Fatalf("Error encoding %T: %v", resp, err) return } if resp.Error != nil { log.Printf("Error in response: %s", *resp.Error) } for len(output) > 0 { n, err := os.Stdout.Write(output) if n > len(output) { n = len(output) } output = output[n:] if err != nil { time.Sleep(time.Millisecond * 500) log.Printf("Error writing output to standard out: %v", err) } } }() var req compiler.CodeGeneratorRequest { var input bytes.Buffer if n, err := input.ReadFrom(os.Stdin); err != nil { resp.Error = heapString("error reading from standard input: " + err.Error()) return } else if n == 0 { resp.Error = heapString("no input provided") return } if err := proto.Unmarshal(input.Bytes(), &req); err != nil { resp.Error = heapString("error unmarshalling from standard input: " + err.Error()) return } } params := parseParameters(req.GetParameter()) files := make(map[string]*bytes.Buffer) root := FlatTypeRoot{ Request: &req, Visible: getFlatTypes(&req, false, nil), Exported: getFlatTypes(&req, true, nil), Params: params, HasData: false, ExecParam: nil, } left, right := "(*", "*)" if p := params.Get("left"); len(p) > 0 { left = p } if p := params.Get("right"); len(p) > 0 { right = p } // This code is all awful but at least it gets the job done right now. var tx *template.Template funcs := template.FuncMap{ "find": (typeFinder{root.Request}).Find, "fexec": func(name, outfile string, data ...interface{}) error { subroot := root if len(data) == 1 { d := data[0] if _, ok := d.(FlatTypeRoot); !ok { subroot.ExecParam = d } } else if len(data) > 1 { subroot.ExecParam = data } var out io.Writer = ioutil.Discard if len(name) > 0 { b, ok := files[outfile] if !ok { b = &bytes.Buffer{} files[outfile] = b } out = b subroot.HasData = b.Len() > 0 } if name != "" { return tx.ExecuteTemplate(out, name, subroot) } else { return tx.Execute(out, subroot) } }, "exec": func(name string, dot ...interface{}) (string, error) { var data interface{} = dot if len(dot) == 1 { data = dot[0] } else if len(dot) == 0 { data = nil } var buf bytes.Buffer var err error if name != "" { err = tx.ExecuteTemplate(&buf, name, data) } else { err = tx.Execute(&buf, data) } return buf.String(), err }, } tx = template.New("").Delims(left, right).Funcs(mergeTypeChecks(copyDefaultTemplateFuncs(funcs))) tx, err := tx.ParseFiles(params["template"]...) if err != nil { resp.Error = heapString("error parsing template(s): " + err.Error()) return } templates := params["template"] if tn := params["exec"]; len(tn) > 0 { templates = tn } for _, name := range templates { if err := tx.ExecuteTemplate(ioutil.Discard, name, root); err != nil { resp.Error = heapString(err.Error()) return } } for name, buf := range files { f := &compiler.CodeGeneratorResponse_File{ Name: heapString(name), Content: heapString(buf.String()), } log.Printf("OUT=%q", name) resp.File = append(resp.File, f) } }