-
Notifications
You must be signed in to change notification settings - Fork 16
/
gen.go
137 lines (122 loc) · 2.84 KB
/
gen.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//go:build ignore
package main
import (
"encoding/csv"
"io"
"log"
"os"
"sort"
"strings"
"text/template"
"unicode"
"unicode/utf8"
)
const codeTemplate = `
// Code generated by gen.go; DO NOT EDIT.
package multicodec
const (
{{- range .Entries }}
// {{ if .IsDeprecated }}Deprecated: {{ end }}{{ .ConstName }} is a {{ .Status }} code tagged "{{ .Tag }}"{{ if .Description }} and described by: {{ .Description }}{{ end }}.
{{ .ConstName }} Code = {{ .Code }} // {{ .Name }}
{{ end -}}
)
var knownCodes = []Code{
{{- range .Entries }}
{{ .ConstName }},
{{- end }}
}
func (c Code) Tag() string {
switch c {
{{- range $i, $tag := .Tags }}
case {{ $first := true }}
{{- range $.Entries }}
{{- /* we don't include the only deprecated code, as it's a duplicate */ -}}
{{- if not .IsDeprecated }}{{ if eq .Tag $tag }}
{{- if not $first }},
{{ end }}{{ $first = false -}}
{{ .ConstName -}}
{{ end }}{{ end -}}
{{ end -}}
:
return {{ printf "%q" $tag }}
{{ end -}}
default:
return "<unknown>"
}
}
`
type tableEntry struct {
Name string
Tag string
Code string
Status string
Description string
}
func (c tableEntry) IsDeprecated() bool {
return strings.Contains(c.Description, "deprecated")
}
func (c tableEntry) ConstName() string {
var b strings.Builder
var last rune
for _, part := range strings.Split(c.Name, "-") {
first, firstSize := utf8.DecodeRuneInString(part)
if unicode.IsNumber(last) && unicode.IsNumber(first) {
// 123-456 should result in 123_456 for readability.
b.WriteByte('_')
}
b.WriteRune(unicode.ToUpper(first))
b.WriteString(part[firstSize:])
last, _ = utf8.DecodeLastRuneInString(part)
}
return b.String()
}
func main() {
f, err := os.Open("multicodec/table.csv")
if err != nil {
log.Fatal(err)
}
defer f.Close()
var tmplData struct {
Entries []tableEntry
Tags []string
}
tags := make(map[string]bool)
csvReader := csv.NewReader(f)
csvReader.Read() // skip the header line
for {
record, err := csvReader.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
entry := tableEntry{
Name: strings.TrimSpace(record[0]),
Tag: strings.TrimSpace(record[1]),
Code: strings.TrimSpace(record[2]),
Status: strings.TrimSpace(record[3]),
Description: strings.TrimSpace(record[4]),
}
tmplData.Entries = append(tmplData.Entries, entry)
tags[entry.Tag] = true // use a map to deduplicate
}
for tag := range tags {
tmplData.Tags = append(tmplData.Tags, tag)
}
sort.Strings(tmplData.Tags)
tmpl, err := template.New("").
Funcs(template.FuncMap{"ToTitle": strings.Title}).
Parse(codeTemplate)
if err != nil {
log.Fatal(err)
}
out, err := os.Create("code_table.go")
if err != nil {
log.Fatal(err)
}
defer out.Close()
if err := tmpl.Execute(out, tmplData); err != nil {
log.Fatal(err)
}
}