events/generate/events_generate.go (146 lines of code) (raw):
// This binary generates usable Go code from the data files.
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"text/template"
)
var (
// Use [[ and ]] as deliminators, as we're writing struct definitions with many {}.
tmpl = template.Must(template.New("events").Delims("[[", "]]").Parse(eventDataTemplate))
)
const (
input = "input"
output = "output"
converted = "converted"
legacyType = "legacy"
cloudeventType = "cloudevent"
dataDir = "generate/data"
outputFile = "events_data.go"
eventDataTemplate = `// Code generated by events_generate.go. DO NOT EDIT.
package events
type EventData struct {
LegacyEvent []byte
CloudEvent []byte
}
type Event struct {
Input EventData
Output EventData
ConvertedOutput EventData
}
var Events = map[string]Event{[[ range $k, $v := . ]]
"[[ $k ]]": {
Input: EventData{[[ if $v.LegacyInput ]]
LegacyEvent: [[ $v.LegacyInput ]],[[ end ]][[ if $v.CloudEventInput ]]
CloudEvent: [[ $v.CloudEventInput ]],[[ end ]]
},
Output: EventData{[[ if $v.LegacyOutput ]]
LegacyEvent: [[ $v.LegacyOutput ]],[[ end ]][[ if $v.CloudEventOutput ]]
CloudEvent: [[ $v.CloudEventOutput ]],[[ end ]]
},
ConvertedOutput: EventData{[[ if $v.ConvertedLegacyOutput ]]
LegacyEvent: [[ $v.ConvertedLegacyOutput ]],[[ end ]][[ if $v.ConvertedCloudEventOutput ]]
CloudEvent: [[ $v.ConvertedCloudEventOutput ]],[[ end ]]
},
},
[[ end ]]}
`
)
type eventData struct {
LegacyInput string
LegacyOutput string
CloudEventInput string
CloudEventOutput string
ConvertedCloudEventOutput string
ConvertedLegacyOutput string
}
func breakdownFileName(path string) (string, string, bool) {
// Must be a JSON file.
if !strings.HasSuffix(path, ".json") {
return "", "", false
}
fileName := strings.TrimSuffix(path, ".json")
isConverted := strings.HasSuffix(fileName, converted)
if isConverted {
fileName = strings.TrimSuffix(fileName, "-"+converted)
}
var et, ft string
if strings.HasSuffix(fileName, input) {
ft = input
fileName = strings.TrimSuffix(fileName, "-"+input)
} else if strings.HasSuffix(fileName, output) {
ft = output
fileName = strings.TrimSuffix(fileName, "-"+output)
}
if strings.HasSuffix(fileName, legacyType) {
et = legacyType
fileName = strings.TrimSuffix(fileName, "-"+legacyType)
} else if strings.HasSuffix(fileName, cloudeventType) {
et = cloudeventType
fileName = strings.TrimSuffix(fileName, "-"+cloudeventType)
}
return fileName, et + ft, isConverted
}
func main() {
events := make(map[string]*eventData)
err := filepath.Walk(dataDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return fmt.Errorf("accessing path %q: %v", path, err)
}
if info.IsDir() {
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
// A source file not existing is fine.
if os.IsNotExist(err) {
return nil
}
return fmt.Errorf("reading file %q: %v", path, err)
}
if data == nil {
return nil
}
name, t, c := breakdownFileName(info.Name())
if name == "" {
return nil
}
ed, ok := events[name]
if !ok {
ed = &eventData{}
events[name] = ed
}
d := "[]byte(`" + string(data) + "`)"
switch t {
case legacyType + input:
ed.LegacyInput = d
case legacyType + output:
if c {
ed.ConvertedLegacyOutput = d
} else {
ed.LegacyOutput = d
}
case cloudeventType + input:
ed.CloudEventInput = d
case cloudeventType + output:
if c {
ed.ConvertedCloudEventOutput = d
} else {
ed.CloudEventOutput = d
}
}
return nil
})
if err != nil {
log.Fatalf("walking %q: %v", dataDir, err)
}
f, err := os.Create(outputFile)
if err != nil {
log.Fatalf("creating event_data.go: %v", err)
}
defer f.Close()
if err := tmpl.Execute(f, events); err != nil {
log.Fatalf("executing template: %v", err)
}
return
}