go-json/cmd/generator/main.go

467 lines
16 KiB
Go

package main
import (
"bytes"
"fmt"
"go/format"
"io/ioutil"
"path/filepath"
"runtime"
"strings"
"text/template"
)
type opType struct {
Op string
IndentOp string
Code string
}
type headType struct {
Head string
PtrHead string
NPtrHead string
AnonymousHead string
AnonymousPtrHead string
AnonymousNPtrHead string
OmitEmptyHead string
OmitEmptyPtrHead string
OmitEmptyNPtrHead string
AnonymousOmitEmptyHead string
AnonymousOmitEmptyPtrHead string
AnonymousOmitEmptyNPtrHead string
StringTagHead string
StringTagPtrHead string
StringTagNPtrHead string
AnonymousStringTagHead string
AnonymousStringTagPtrHead string
AnonymousStringTagNPtrHead string
}
type fieldType struct {
Field string
OmitEmptyField string
StringTagField string
}
func _main() error {
tmpl, err := template.New("").Parse(`// Code generated by cmd/generator. DO NOT EDIT!
package json
type codeType int
const (
{{- range $index, $type := .CodeTypes }}
code{{ $type }} codeType = {{ $index }}
{{- end }}
)
type opType int
const (
{{- range $index, $type := .OpTypes }}
op{{ $type.Op }} opType = {{ $index }}
{{- end }}
)
func (t opType) String() string {
switch t {
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return "{{ $type.Op }}"
{{- end }}
}
return ""
}
func (t opType) codeType() codeType {
switch t {
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return code{{ $type.Code }}
{{- end }}
}
return codeOp
}
func (t opType) toIndent() opType {
switch t {
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ $type.IndentOp }}
{{- end }}
}
return t
}
func (t opType) headToPtrHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.PtrHead }}
case op{{ $type.AnonymousHead }}:
return op{{ $type.AnonymousPtrHead }}
case op{{ $type.OmitEmptyHead }}:
return op{{ $type.OmitEmptyPtrHead }}
case op{{ $type.AnonymousOmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }}
case op{{ $type.StringTagHead }}:
return op{{ $type.StringTagPtrHead }}
case op{{ $type.AnonymousStringTagHead }}:
return op{{ $type.AnonymousStringTagPtrHead }}
{{- end }}
}
return t
}
func (t opType) headToNPtrHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.NPtrHead }}
case op{{ $type.AnonymousHead }}:
return op{{ $type.AnonymousNPtrHead }}
case op{{ $type.OmitEmptyHead }}:
return op{{ $type.OmitEmptyNPtrHead }}
case op{{ $type.AnonymousOmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyNPtrHead }}
case op{{ $type.StringTagHead }}:
return op{{ $type.StringTagNPtrHead }}
case op{{ $type.AnonymousStringTagHead }}:
return op{{ $type.AnonymousStringTagNPtrHead }}
{{- end }}
}
return t
}
func (t opType) headToAnonymousHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.AnonymousHead }}
case op{{ $type.PtrHead }}:
return op{{ $type.AnonymousPtrHead }}
case op{{ $type.OmitEmptyHead }}:
return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.OmitEmptyPtrHead }}:
return op{{ $type.AnonymousOmitEmptyPtrHead }}
case op{{ $type.StringTagHead }}:
return op{{ $type.AnonymousStringTagHead }}
case op{{ $type.StringTagPtrHead }}:
return op{{ $type.AnonymousStringTagPtrHead }}
{{- end }}
}
return t
}
func (t opType) headToOmitEmptyHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.OmitEmptyHead }}
case op{{ $type.PtrHead }}:
return op{{ $type.OmitEmptyPtrHead }}
{{- end }}
}
return t
}
func (t opType) headToStringTagHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.Head }}:
return op{{ $type.StringTagHead }}
case op{{ $type.PtrHead }}:
return op{{ $type.StringTagPtrHead }}
{{- end }}
}
return t
}
func (t opType) ptrHeadToHead() opType {
switch t {
{{- range $type := .HeadTypes }}
case op{{ $type.PtrHead }}, op{{ $type.NPtrHead }}:
return op{{ $type.Head }}
case op{{ $type.AnonymousPtrHead }}, op{{ $type.AnonymousNPtrHead }}:
return op{{ $type.AnonymousHead }}
case op{{ $type.OmitEmptyPtrHead }}, op{{ $type.OmitEmptyNPtrHead }}:
return op{{ $type.OmitEmptyHead }}
case op{{ $type.AnonymousOmitEmptyPtrHead }}, op{{ $type.AnonymousOmitEmptyNPtrHead }}:
return op{{ $type.AnonymousOmitEmptyHead }}
case op{{ $type.StringTagPtrHead }}, op{{ $type.StringTagNPtrHead }}:
return op{{ $type.StringTagHead }}
case op{{ $type.AnonymousStringTagPtrHead }}, op{{ $type.AnonymousStringTagNPtrHead }}:
return op{{ $type.AnonymousStringTagHead }}
{{- end }}
}
return t
}
func (t opType) fieldToOmitEmptyField() opType {
switch t {
{{- range $type := .FieldTypes }}
case op{{ $type.Field }}:
return op{{ $type.OmitEmptyField }}
{{- end }}
}
return t
}
func (t opType) fieldToStringTagField() opType {
switch t {
{{- range $type := .FieldTypes }}
case op{{ $type.Field }}:
return op{{ $type.StringTagField }}
{{- end }}
}
return t
}
`)
if err != nil {
return err
}
codeTypes := []string{
"Op",
"ArrayHead",
"ArrayElem",
"SliceHead",
"SliceElem",
"MapHead",
"MapKey",
"MapValue",
"MapEnd",
"StructFieldRecursive",
"StructField",
}
primitiveTypes := []string{
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64",
"float32", "float64", "bool", "string", "bytes",
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
"intString", "int8String", "int16String", "int32String", "int64String",
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
"intPtr", "int8Ptr", "int16Ptr", "int32Ptr", "int64Ptr",
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "bytesPtr",
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "bytesNPtr",
}
primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes {
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
}
opTypes := []opType{
{"End", "EndIndent", "Op"},
{"Interface", "InterfaceIndent", "Op"},
{"InterfaceEnd", "InterfaceEndIndent", "Op"},
{"Ptr", "PtrIndent", "Op"},
{"NPtr", "NPtrIndent", "Op"},
{"SliceHead", "SliceHeadIndent", "SliceHead"},
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
{"SliceElem", "SliceElemIndent", "SliceElem"},
{"RootSliceElem", "RootSliceElemIndent", "SliceElem"},
{"SliceEnd", "SliceEndIndent", "Op"},
{"ArrayHead", "ArrayHeadIndent", "ArrayHead"},
{"ArrayElem", "ArrayElemIndent", "ArrayElem"},
{"ArrayEnd", "ArrayEndIndent", "Op"},
{"MapHead", "MapHeadIndent", "MapHead"},
{"MapHeadLoad", "MapHeadLoadIndent", "MapHead"},
{"MapKey", "MapKeyIndent", "MapKey"},
{"MapValue", "MapValueIndent", "MapValue"},
{"MapEnd", "MapEndIndent", "Op"},
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
{"StructFieldHeadStringTag", "StructFieldHeadStringTagIndent", "StructField"},
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldNPtrAnonymousHeadOmitEmpty", "StructFieldNPtrAnonymousHeadOmitEmptyIndent", "StructField"},
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldNPtrAnonymousHeadStringTag", "StructFieldNPtrAnonymousHeadStringTagIndent", "StructField"},
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
{"StructFieldNPtrHead", "StructFieldNPtrHeadIndent", "StructField"},
{"StructFieldNPtrHeadOmitEmpty", "StructFieldNPtrHeadOmitEmptyIndent", "StructField"},
{"StructFieldNPtrHeadStringTag", "StructFieldNPtrHeadStringTagIndent", "StructField"},
{"StructFieldNPtrAnonymousHead", "StructFieldNPtrAnonymousHeadIndent", "StructField"},
{"StructField", "StructFieldIndent", "StructField"},
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
{"StructFieldRecursiveEnd", "StructFieldRecursiveEndIndent", "Op"},
{"StructEnd", "StructEndIndent", "StructField"},
{"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"},
}
for _, typ := range primitiveTypesUpper {
opTypes = append(opTypes, opType{
Op: typ,
IndentOp: fmt.Sprintf("%sIndent", typ),
Code: "Op",
})
}
for _, prefix := range []string{
"StructFieldHead",
"StructFieldHeadOmitEmpty",
"StructFieldHeadStringTag",
"StructFieldAnonymousHead",
"StructFieldAnonymousHeadOmitEmpty",
"StructFieldAnonymousHeadStringTag",
"StructFieldPtrHead",
"StructFieldPtrHeadOmitEmpty",
"StructFieldPtrHeadStringTag",
"StructFieldPtrAnonymousHead",
"StructFieldPtrAnonymousHeadOmitEmpty",
"StructFieldPtrAnonymousHeadStringTag",
"StructFieldNPtrHead",
"StructFieldNPtrHeadOmitEmpty",
"StructFieldNPtrHeadStringTag",
"StructFieldNPtrAnonymousHead",
"StructFieldNPtrAnonymousHeadOmitEmpty",
"StructFieldNPtrAnonymousHeadStringTag",
"StructField",
//"StructFieldPtr",
//"StructFieldNPtr",
"StructFieldOmitEmpty",
"StructFieldStringTag",
} {
for _, typ := range primitiveTypesUpper {
opTypes = append(opTypes, opType{
Op: fmt.Sprintf("%s%s", prefix, typ),
IndentOp: fmt.Sprintf("%s%sIndent", prefix, typ),
Code: "StructField",
})
}
}
for _, typ := range opTypes {
opTypes = append(opTypes, opType{
Op: typ.IndentOp,
IndentOp: typ.IndentOp,
Code: typ.Code,
})
}
base := headType{
Head: "StructFieldHead",
PtrHead: "StructFieldPtrHead",
NPtrHead: "StructFieldNPtrHead",
AnonymousHead: "StructFieldAnonymousHead",
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
AnonymousNPtrHead: "StructFieldNPtrAnonymousHead",
OmitEmptyHead: "StructFieldHeadOmitEmpty",
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
OmitEmptyNPtrHead: "StructFieldNPtrHeadOmitEmpty",
StringTagHead: "StructFieldHeadStringTag",
StringTagPtrHead: "StructFieldPtrHeadStringTag",
StringTagNPtrHead: "StructFieldNPtrHeadStringTag",
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
AnonymousOmitEmptyNPtrHead: "StructFieldNPtrAnonymousHeadOmitEmpty",
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
AnonymousStringTagNPtrHead: "StructFieldNPtrAnonymousHeadStringTag",
}
headTypes := []headType{base}
for _, prim := range primitiveTypesUpper {
headTypes = append(headTypes, headType{
Head: fmt.Sprintf("%s%s", base.Head, prim),
PtrHead: fmt.Sprintf("%s%s", base.PtrHead, prim),
NPtrHead: fmt.Sprintf("%s%s", base.NPtrHead, prim),
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
AnonymousNPtrHead: fmt.Sprintf("%s%s", base.AnonymousNPtrHead, prim),
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
OmitEmptyNPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyNPtrHead, prim),
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
AnonymousOmitEmptyNPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyNPtrHead, prim),
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim),
StringTagNPtrHead: fmt.Sprintf("%s%s", base.StringTagNPtrHead, prim),
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, prim),
AnonymousStringTagNPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagNPtrHead, prim),
})
}
for _, typ := range headTypes {
headTypes = append(headTypes, headType{
Head: fmt.Sprintf("%sIndent", typ.Head),
PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead),
NPtrHead: fmt.Sprintf("%sIndent", typ.NPtrHead),
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
AnonymousNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousNPtrHead),
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
OmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyNPtrHead),
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
AnonymousOmitEmptyNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyNPtrHead),
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
StringTagNPtrHead: fmt.Sprintf("%sIndent", typ.StringTagNPtrHead),
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead),
AnonymousStringTagNPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagNPtrHead),
})
}
baseField := fieldType{
Field: "StructField",
OmitEmptyField: "StructFieldOmitEmpty",
StringTagField: "StructFieldStringTag",
}
fieldTypes := []fieldType{baseField}
for _, prim := range primitiveTypesUpper {
fieldTypes = append(fieldTypes, fieldType{
Field: fmt.Sprintf("%s%s", baseField.Field, prim),
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
StringTagField: fmt.Sprintf("%s%s", baseField.StringTagField, prim),
})
}
for _, typ := range fieldTypes {
fieldTypes = append(fieldTypes, fieldType{
Field: fmt.Sprintf("%sIndent", typ.Field),
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
StringTagField: fmt.Sprintf("%sIndent", typ.StringTagField),
})
}
var b bytes.Buffer
if err := tmpl.Execute(&b, struct {
CodeTypes []string
OpTypes []opType
HeadTypes []headType
FieldTypes []fieldType
}{
CodeTypes: codeTypes,
OpTypes: opTypes,
HeadTypes: headTypes,
FieldTypes: fieldTypes,
}); err != nil {
return err
}
path := filepath.Join(repoRoot(), "encode_optype.go")
buf, err := format.Source(b.Bytes())
if err != nil {
return err
}
return ioutil.WriteFile(path, buf, 0644)
}
func repoRoot() string {
_, file, _, _ := runtime.Caller(0)
relativePathFromRepoRoot := filepath.Join("cmd", "generator")
return strings.TrimSuffix(filepath.Dir(file), relativePathFromRepoRoot)
}
func main() {
if err := _main(); err != nil {
panic(err)
}
}