func main() { // Begin by allocating a generator. The request and response structures are stored there // so we can do error handling easily - the response structure contains the field to // report failure. g := generator.New() data, err := ioutil.ReadAll(os.Stdin) if err != nil { g.Error(err, "reading input") } if err := proto.Unmarshal(data, g.Request); err != nil { g.Error(err, "parsing input proto") } // generator处理数命令行参数(?) if len(g.Request.FileToGenerate) == 0 { g.Fail("no files to generate") } g.CommandLineParameters(g.Request.GetParameter()) // Create a wrapped version of the Descriptors and EnumDescriptors that // point to the file that defines them. g.WrapTypes() g.SetPackageNames() g.BuildTypeNameMap() g.GenerateAllFiles() // Send back the results. data, err = proto.Marshal(g.Response) if err != nil { g.Error(err, "failed to marshal output proto") } _, err = os.Stdout.Write(data) if err != nil { g.Error(err, "failed to write output proto") } }
func main() { // Begin by allocating a generator. The request and response structures are stored there // so we can do error handling easily - the response structure contains the field to // report failure. str := `{"cmd_name":"Pmd.UserJsMessageForwardUserPmd_CS","msg":{"errno":"0","st":1470339434,"data":{"ret":0,"uid":1126119,"errno":"0","userInfo":{"roundNum":41,"signature":"","gender":"男","giftCoupon":0,"nickName":"1126119","headUrl":"http:\/\/1251210123.cdn.myqcloud.com\/1251210123\/QZONESTATIC\/headImages\/97.jpg","uid":1126119,"remainder":17187041,"maxMulti":59,"sumRecharge":0,"platId":0,"subPlatId":0,"bankChips":0},"gmLevel":0,"roomInfo":[{"lowestCarry":1,"maxSeat":20,"bankerConfig":{"selectChips":[3000000,5000000,8000000,10000000],"lowestBankerChips":3000000},"lowestBet":100,"roomName":"房间10002","roomId":10002,"maxUser":10000},{"lowestCarry":500000,"maxSeat":20,"bankerConfig":{"selectChips":[30000000,50000000,80000000,100000000],"lowestBankerChips":30000000},"lowestBet":100,"roomName":"房间10004","roomId":10004,"maxUser":10000}]},"do":"Cmd.UserInfoSynRequestLobbyCmd_S"}}` var jsmap map[string]interface{} err1 := json.Unmarshal([]byte(str), &jsmap) if err1 != nil { fmt.Println(err1) } proto.MarshalMessageSetJSON g := generator.New() file, er := os.Open("/tmp/pmd.pb") if er != nil { g.Error(er, "reading input") } data, err := ioutil.ReadAll(file) if err != nil { g.Error(err, "reading input") } if err := proto.Unmarshal(data, g.Request); err != nil { g.Error(err, "parsing input proto") } if len(g.Request.FileToGenerate) == 0 { g.Fail("no files to generate") } fmt.Println(g.Request.ProtoFile) fmt.Println(g.Request.FileToGenerate) //g.Request.FileToGenerate[0] = "pmd.proto" //g.Request.FileToGenerate = append(g.Request.FileToGenerate, "pmd.proto") //fmt.Println(g.Request.FileToGenerate[0]) //fmt.Println(g.Request.Parameter) //fmt.Println(g.Request.ProtoFile) //fmt.Println(g.Request.XXX_unrecognized) //g.CommandLineParameters(g.Request.GetParameter()) // Create a wrapped version of the Descriptors and EnumDescriptors that // point to the file that defines them. //g.WrapTypes() fmt.Println("XXXXXXXXXXXXXXXXXXXXX") //g.SetPackageNames() fmt.Println("XXXXXXXXXXXXXXXXXXXXX") //g.BuildTypeNameMap() //g.GenerateAllFiles() // Send back the results. data, err = proto.Marshal(g.Response) //if err != nil { // g.Error(err, "failed to marshal output proto") //} //_, err = os.Stdout.Write(data) if err != nil { g.Error(err, "failed to write output proto") } //file.Write(data) file.Close() }
// Read from standard input func main() { g := generator.New() data, err := ioutil.ReadAll(os.Stdin) if err != nil { failWithError(err, "reading input") } if err := proto.Unmarshal(data, g.Request); err != nil { failWithError(err, "parsing input proto") } if len(g.Request.FileToGenerate) == 0 { fail("no files to generate") } g.CommandLineParameters(g.Request.GetParameter()) if val, ok := g.Param["logtostderr"]; ok && val == "true" { logtostderr = true } tree := buildTree(g.Request.GetProtoFile()) packageLocations := make(map[string]string) for _, file := range g.Request.GetProtoFile() { loc := file.GetName()[:strings.LastIndex(file.GetName(), "/")] packageLocations[file.GetPackage()] = loc } selectedServices := make(map[string]string) for k, v := range g.Param { switch { case k == "logtostderr": if v == "true" { logtostderr = true } case strings.HasPrefix(k, "."): selectedServices[k] = v } } for serviceKey := range selectedServices { service, ok := tree.services[serviceKey] if !ok { fail("Service", serviceKey, "unknown") } usedMessages := make(map[string]*message) usedEnums := make(map[string]*enum) content := new(bytes.Buffer) fmt.Fprintf(content, "# %s API Reference\n\n", service.GetName()) if service.comment != "" { fmt.Fprintf(content, "%s\n\n", service.comment) } if len(service.methods) > 0 { fmt.Fprint(content, "## Methods\n\n") for _, method := range service.methods { fmt.Fprintf(content, "### `%s`\n\n", method.GetName()) if method.comment != "" { fmt.Fprintf(content, "%s\n\n", method.comment) } if method.inputStream { fmt.Fprintf(content, "- Client stream of [`%s`](#%s)\n", method.input.GetName(), heading(method.input.key)) } else { fmt.Fprintf(content, "- Request: [`%s`](#%s)\n", method.input.GetName(), heading(method.input.key)) } useMessage(tree, method.input, usedMessages, usedEnums) if method.outputStream { fmt.Fprintf(content, "- Server stream of [`%s`](#%s)\n", method.output.GetName(), heading(method.input.key)) } else { fmt.Fprintf(content, "- Response: [`%s`](#%s)\n", method.output.GetName(), heading(method.input.key)) } useMessage(tree, method.output, usedMessages, usedEnums) fmt.Fprintln(content) if len(method.endpoints) != 0 { if len(method.endpoints) == 1 { fmt.Fprint(content, "#### HTTP Endpoint\n\n") } else { fmt.Fprint(content, "#### HTTP Endpoints\n\n") } for _, endpoint := range method.endpoints { fmt.Fprintf(content, "- `%s` `%s`", endpoint.method, endpoint.url) var params []string for _, match := range regexp.MustCompile(`\{([a-z_]+)\}`).FindAllStringSubmatch(endpoint.url, -1) { if match != nil && len(match) == 2 && match[1] != "" { params = append(params, fmt.Sprintf("`%s`", match[1])) } } if len(params) > 0 { fmt.Fprintf(content, "(%s can be left out of the request body)", strings.Join(params, ", ")) } fmt.Fprintln(content) } fmt.Fprintln(content) fmt.Fprint(content, "#### JSON Request Format\n\n") fmt.Fprintf(content, "```json\n%s\n```\n\n", method.input.JSONExample(tree)) fmt.Fprint(content, "#### JSON Response Format\n\n") fmt.Fprintf(content, "```json\n%s\n```\n\n", method.output.JSONExample(tree)) } } } if len(usedMessages) > 0 { fmt.Fprint(content, "## Messages\n\n") var messageKeys []string for key := range usedMessages { messageKeys = append(messageKeys, key) } sort.Strings(messageKeys) for _, messageKey := range messageKeys { message := usedMessages[messageKey] fmt.Fprintf(content, "### `%s`\n\n", message.key) if strings.HasPrefix(messageKey, ".google") { fmt.Fprintf(content, "%s\n\n", strings.SplitAfter(message.comment, ".")[0]) } else if message.comment != "" { fmt.Fprintf(content, "%s\n\n", message.comment) } if len(message.fields) > 0 { fmt.Fprintln(content, "| Field Name | Type | Description |") fmt.Fprintln(content, "| ---------- | ---- | ----------- |") for idx, field := range message.fields { if field.isOneOf { if idx == 0 || !message.fields[idx-1].isOneOf || message.fields[idx-1].GetOneofIndex() != field.GetOneofIndex() { oneof := message.GetOneof(field.GetOneofIndex()) if len(oneof.fields) > 1 { fmt.Fprintf(content, "| **%s** | **oneof %d** | one of the following %d |\n", oneof.GetName(), len(oneof.fields), len(oneof.fields)) } } } else { if idx > 0 && message.fields[idx-1].isOneOf { oneof := message.GetOneof(message.fields[idx-1].GetOneofIndex()) if len(oneof.fields) > 1 { fmt.Fprintf(content, "| **%s** | **end oneof %d** | |\n", oneof.GetName(), len(oneof.fields)) } } } var fieldType string if field.repeated { fieldType += "_repeated_ " } typ := strings.ToLower(strings.TrimPrefix(field.GetType().String(), "TYPE_")) switch typ { case "message": friendlyType := field.GetTypeName()[strings.LastIndex(field.GetTypeName(), ".")+1:] fieldType += fmt.Sprintf("[`%s`](#%s)", friendlyType, heading(field.GetTypeName())) case "enum": // TODO(htdvisser): test this if enum, ok := tree.enums[field.GetTypeName()]; ok { usedEnums[field.GetTypeName()] = enum } friendlyType := field.GetTypeName()[strings.LastIndex(field.GetTypeName(), ".")+1:] fieldType += fmt.Sprintf("[`%s`](#%s)", friendlyType, heading(field.GetTypeName())) default: fieldType += fmt.Sprintf("`%s`", typ) } fmt.Fprintf(content, "| `%s` | %s | %s |\n", field.GetName(), fieldType, strings.Replace(field.comment, "\n", " ", -1)) } fmt.Fprintln(content) } } } if len(usedEnums) > 0 { fmt.Fprint(content, "## Used Enums\n\n") var enumKeys []string for key := range usedEnums { enumKeys = append(enumKeys, key) } sort.Strings(enumKeys) for _, enumKey := range enumKeys { enum := usedEnums[enumKey] fmt.Fprintf(content, "### `%s`\n\n", enum.key) if enum.comment != "" { fmt.Fprintf(content, "%s\n\n", enum.comment) } if len(enum.values) > 0 { fmt.Fprintln(content, "| Value | Description |") fmt.Fprintln(content, "| ----- | ----------- |") for _, value := range enum.values { fmt.Fprintf(content, "| `%s` | %s |\n", value.GetName(), strings.Replace(value.comment, "\n", " ", -1)) } fmt.Fprintln(content) } } } packageService := strings.TrimPrefix(service.key, ".") packageName := packageService[:strings.Index(packageService, ".")] location, ok := packageLocations[packageName] if !ok { fail("Could not find location of package", packageName) } fileName := path.Join(location, service.GetName()+".md") contentString := content.String() g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{ Name: &fileName, Content: &contentString, }) } // Send back the results. data, err = proto.Marshal(g.Response) if err != nil { failWithError(err, "failed to marshal output proto") } _, err = os.Stdout.Write(data) if err != nil { failWithError(err, "failed to write output proto") } }