180 lines
4.2 KiB
Go
180 lines
4.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"log"
|
||
|
"os"
|
||
|
"os/exec"
|
||
|
"strings"
|
||
|
"text/template"
|
||
|
)
|
||
|
|
||
|
type Protocol struct {
|
||
|
Types map[string]map[string]*Type
|
||
|
Actions map[string]map[string]*Action
|
||
|
}
|
||
|
|
||
|
type Type struct {
|
||
|
Fields map[string]*DataType
|
||
|
Request bool `json:"-"`
|
||
|
Doc string
|
||
|
}
|
||
|
|
||
|
type DataType struct {
|
||
|
List bool
|
||
|
Type string
|
||
|
Version string
|
||
|
FieldName string
|
||
|
Doc string
|
||
|
}
|
||
|
|
||
|
type Action struct {
|
||
|
FnName string
|
||
|
Request string
|
||
|
Response string
|
||
|
Doc string
|
||
|
}
|
||
|
|
||
|
type StructsTemplateInput struct {
|
||
|
Types map[string]*Type
|
||
|
Version string
|
||
|
ImportVersions []string
|
||
|
}
|
||
|
|
||
|
type ActionsTemplateInput struct {
|
||
|
Actions map[string]*Action
|
||
|
Version string
|
||
|
Responses bool
|
||
|
}
|
||
|
|
||
|
var typeMap = map[string]string{
|
||
|
"int": "int32",
|
||
|
"Integer": "int32",
|
||
|
"Boolean": "bool",
|
||
|
"long": "int64",
|
||
|
"Long": "int64",
|
||
|
"UUID": "string",
|
||
|
"boolean": "bool",
|
||
|
"String": "string",
|
||
|
"Map": "map[string]string", // TODO: make signald print the actual key and value types
|
||
|
}
|
||
|
|
||
|
var fieldNameMap = map[string]string{
|
||
|
"id": "ID",
|
||
|
"recipientGroupId": "RecipientGroupID",
|
||
|
"uuid": "UUID",
|
||
|
}
|
||
|
|
||
|
func (d *DataType) fixForVersion(field, version string) {
|
||
|
response, ok := typeMap[d.Type]
|
||
|
if ok {
|
||
|
if d.Type == "byte" && d.List {
|
||
|
d.List = false
|
||
|
}
|
||
|
d.Type = response
|
||
|
} else {
|
||
|
if d.Version == version || d.Version == "" {
|
||
|
d.Type = fmt.Sprintf("*%s", d.Type)
|
||
|
} else {
|
||
|
d.Type = fmt.Sprintf("*%s.%s", d.Version, d.Type)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fieldName, ok := fieldNameMap[field]
|
||
|
if ok {
|
||
|
d.FieldName = fieldName
|
||
|
} else {
|
||
|
d.FieldName = strings.Title(field)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
var response Protocol
|
||
|
err := json.NewDecoder(os.Stdin).Decode(&response)
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nError parsing stdin")
|
||
|
}
|
||
|
|
||
|
tmpl, err := template.ParseGlob("tools/generator/*.tmpl")
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nError parsing templates from tools/generator/*.tmpl")
|
||
|
}
|
||
|
|
||
|
for version, actions := range response.Actions {
|
||
|
inputs := ActionsTemplateInput{Version: version, Responses: false}
|
||
|
for action, a := range actions {
|
||
|
actions[action].FnName = strings.Title(action)
|
||
|
if a.Request != "" {
|
||
|
response.Types[version][a.Request].Request = true
|
||
|
}
|
||
|
if a.Response != "" {
|
||
|
inputs.Responses = true
|
||
|
}
|
||
|
}
|
||
|
inputs.Actions = actions
|
||
|
outputDir := fmt.Sprintf("signald/client-protocol/%s", version)
|
||
|
err = os.MkdirAll(outputDir, os.ModePerm)
|
||
|
if err != nil {
|
||
|
log.Fatal("Error creating", outputDir, err)
|
||
|
}
|
||
|
outputFilename := fmt.Sprintf("%s/%s", outputDir, "requests.go")
|
||
|
log.Println("Opening", outputFilename)
|
||
|
f, err := os.Create(outputFilename)
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nfailed to open output file ", outputFilename)
|
||
|
}
|
||
|
err = tmpl.ExecuteTemplate(f, "requests.go.tmpl", inputs)
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nfailed to render template")
|
||
|
}
|
||
|
err = exec.Command("gofmt", "-w", outputFilename).Run()
|
||
|
if err != nil {
|
||
|
log.Fatal(err, " error running gofmt on ", outputFilename)
|
||
|
}
|
||
|
fmt.Println(outputFilename)
|
||
|
}
|
||
|
|
||
|
for version, types := range response.Types {
|
||
|
inputs := StructsTemplateInput{Version: version}
|
||
|
for typeName, t := range types {
|
||
|
for fieldName, field := range t.Fields {
|
||
|
types[typeName].Fields[fieldName].fixForVersion(fieldName, version)
|
||
|
if field.Version != "" && field.Version != version {
|
||
|
found := false
|
||
|
for _, v := range inputs.ImportVersions {
|
||
|
if v == field.Version {
|
||
|
found = true
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
if !found {
|
||
|
inputs.ImportVersions = append(inputs.ImportVersions, field.Version)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
inputs.Types = types
|
||
|
outputDir := fmt.Sprintf("signald/client-protocol/%s", version)
|
||
|
err = os.MkdirAll(outputDir, os.ModePerm)
|
||
|
if err != nil {
|
||
|
log.Fatal("Error creating", outputDir, err)
|
||
|
}
|
||
|
outputFilename := fmt.Sprintf("%s/%s", outputDir, "structs.go")
|
||
|
log.Println("Opening", outputFilename)
|
||
|
f, err := os.Create(outputFilename)
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nfailed to open output file ", outputFilename)
|
||
|
}
|
||
|
err = tmpl.ExecuteTemplate(f, "structs.go.tmpl", inputs)
|
||
|
if err != nil {
|
||
|
log.Fatal(err, "\nfailed to render template")
|
||
|
}
|
||
|
err = exec.Command("gofmt", "-w", outputFilename).Run()
|
||
|
if err != nil {
|
||
|
log.Fatal(err, " error running gofmt on ", outputFilename)
|
||
|
}
|
||
|
fmt.Println(outputFilename)
|
||
|
}
|
||
|
}
|