go-json/cmd/generator/main.go

533 lines
13 KiB
Go
Raw Normal View History

2020-08-15 11:41:38 +03:00
package main
import (
"bytes"
"fmt"
2020-11-12 18:25:57 +03:00
"go/format"
2020-08-15 11:41:38 +03:00
"io/ioutil"
"path/filepath"
"runtime"
"strings"
"text/template"
)
type opType struct {
2020-12-25 10:06:25 +03:00
Op string
Code string
Indent func() string
2020-12-25 10:38:18 +03:00
Escaped func() string
2020-12-25 10:06:25 +03:00
HeadToPtrHead func() string
HeadToNPtrHead func() string
HeadToAnonymousHead func() string
HeadToOmitEmptyHead func() string
HeadToStringTagHead func() string
PtrHeadToHead func() string
FieldToOmitEmptyField func() string
FieldToStringTagField func() string
2020-08-15 11:41:38 +03:00
}
2020-12-25 10:06:25 +03:00
func createOpType(op, code string) opType {
return opType{
Op: op,
Code: code,
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
2020-12-25 10:38:18 +03:00
Escaped: func() string { return op },
2020-12-25 10:06:25 +03:00
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToOmitEmptyField: func() string { return op },
FieldToStringTagField: func() string { return op },
}
2020-08-15 11:41:38 +03:00
}
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 }}:
2020-12-25 10:06:25 +03:00
return op{{ call $type.Indent }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
2020-12-25 10:38:18 +03:00
func (t opType) toEscaped() opType {
switch t {
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.Escaped }}
{{- end }}
}
return t
}
2020-08-15 11:41:38 +03:00
func (t opType) headToPtrHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToPtrHead }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
2020-12-23 07:13:34 +03:00
func (t opType) headToNPtrHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToNPtrHead }}
2020-12-23 07:13:34 +03:00
{{- end }}
}
return t
}
2020-08-15 11:41:38 +03:00
func (t opType) headToAnonymousHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToAnonymousHead }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
func (t opType) headToOmitEmptyHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToOmitEmptyHead }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
2020-08-19 13:55:06 +03:00
func (t opType) headToStringTagHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.HeadToStringTagHead }}
2020-08-19 13:55:06 +03:00
{{- end }}
}
return t
}
2020-08-15 11:41:38 +03:00
func (t opType) ptrHeadToHead() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.PtrHeadToHead }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
func (t opType) fieldToOmitEmptyField() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.FieldToOmitEmptyField }}
2020-08-15 11:41:38 +03:00
{{- end }}
}
return t
}
2020-08-19 13:55:06 +03:00
func (t opType) fieldToStringTagField() opType {
switch t {
2020-12-25 10:06:25 +03:00
{{- range $type := .OpTypes }}
case op{{ $type.Op }}:
return op{{ call $type.FieldToStringTagField }}
2020-08-19 13:55:06 +03:00
{{- end }}
}
return t
}
2020-08-15 11:41:38 +03:00
`)
if err != nil {
return err
}
codeTypes := []string{
"Op",
"ArrayHead",
"ArrayElem",
"SliceHead",
"SliceElem",
"MapHead",
"MapKey",
"MapValue",
2020-09-16 08:51:37 +03:00
"MapEnd",
2020-08-15 11:41:38 +03:00
"StructFieldRecursive",
"StructField",
}
primitiveTypes := []string{
"int", "int8", "int16", "int32", "int64",
"uint", "uint8", "uint16", "uint32", "uint64",
2020-12-25 10:06:25 +03:00
"float32", "float64", "bool", "string", "escapedString", "bytes",
2020-11-16 15:28:33 +03:00
"array", "map", "mapLoad", "slice", "struct", "MarshalJSON", "MarshalText", "recursive",
"intString", "int8String", "int16String", "int32String", "int64String",
"uintString", "uint8String", "uint16String", "uint32String", "uint64String",
2020-12-23 07:13:34 +03:00
"intPtr", "int8Ptr", "int16Ptr", "int32Ptr", "int64Ptr",
"uintPtr", "uint8Ptr", "uint16Ptr", "uint32Ptr", "uint64Ptr",
2020-12-25 10:06:25 +03:00
"float32Ptr", "float64Ptr", "boolPtr", "stringPtr", "escapedStringPtr", "bytesPtr",
2020-12-23 07:13:34 +03:00
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
2020-12-25 10:06:25 +03:00
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "escapedStringNPtr", "bytesNPtr",
2020-08-15 11:41:38 +03:00
}
primitiveTypesUpper := []string{}
for _, typ := range primitiveTypes {
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
}
opTypes := []opType{
2020-12-25 10:06:25 +03:00
createOpType("End", "Op"),
createOpType("Interface", "Op"),
createOpType("InterfaceEnd", "Op"),
createOpType("Ptr", "Op"),
createOpType("NPtr", "Op"),
createOpType("SliceHead", "SliceHead"),
createOpType("RootSliceHead", "SliceHead"),
createOpType("SliceElem", "SliceElem"),
createOpType("RootSliceElem", "SliceElem"),
createOpType("SliceEnd", "Op"),
createOpType("ArrayHead", "ArrayHead"),
createOpType("ArrayElem", "ArrayElem"),
createOpType("ArrayEnd", "Op"),
createOpType("MapHead", "MapHead"),
createOpType("MapHeadLoad", "MapHead"),
createOpType("MapKey", "MapKey"),
createOpType("MapValue", "MapValue"),
createOpType("MapEnd", "Op"),
createOpType("StructFieldRecursiveEnd", "Op"),
createOpType("StructAnonymousEnd", "StructField"),
2020-08-15 11:41:38 +03:00
}
for _, typ := range primitiveTypesUpper {
2020-12-25 10:06:25 +03:00
typ := typ
2020-12-25 10:38:18 +03:00
optype := createOpType(typ, "Op")
switch typ {
case "String", "StringPtr", "StringNPtr":
optype.Escaped = func() string {
return fmt.Sprintf("Escaped%s", typ)
}
}
opTypes = append(opTypes, optype)
2020-08-15 11:41:38 +03:00
}
2020-12-25 10:06:25 +03:00
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, ptrOrNot := range []string{"", "Ptr", "NPtr"} {
for _, headType := range []string{"", "Anonymous"} {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
ptrOrNot := ptrOrNot
headType := headType
opt := opt
typ := typ
op := fmt.Sprintf(
"Struct%sField%s%sHead%s%s",
escapedOrNot,
ptrOrNot,
headType,
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructField",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
2020-12-25 10:38:18 +03:00
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedField%s%sHead%sEscaped%s",
ptrOrNot,
headType,
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedField%s%sHead%s%s",
ptrOrNot,
headType,
opt,
typ,
)
},
2020-12-25 10:06:25 +03:00
HeadToPtrHead: func() string {
return fmt.Sprintf(
"Struct%sFieldPtr%sHead%s%s",
escapedOrNot,
headType,
opt,
typ,
)
},
HeadToNPtrHead: func() string {
return fmt.Sprintf(
"Struct%sFieldNPtr%sHead%s%s",
escapedOrNot,
headType,
opt,
typ,
)
},
HeadToAnonymousHead: func() string {
return fmt.Sprintf(
"Struct%sField%sAnonymousHead%s%s",
escapedOrNot,
ptrOrNot,
opt,
typ,
)
},
HeadToOmitEmptyHead: func() string {
return fmt.Sprintf(
"Struct%sField%s%sHeadOmitEmpty%s",
escapedOrNot,
ptrOrNot,
headType,
typ,
)
},
HeadToStringTagHead: func() string {
return fmt.Sprintf(
"Struct%sField%s%sHeadStringTag%s",
escapedOrNot,
ptrOrNot,
headType,
typ,
)
},
PtrHeadToHead: func() string {
return fmt.Sprintf(
"Struct%sField%sHead%s%s",
escapedOrNot,
headType,
opt,
typ,
)
},
FieldToOmitEmptyField: func() string { return op },
FieldToStringTagField: func() string { return op },
})
}
}
}
2020-08-15 11:41:38 +03:00
}
}
2020-12-25 10:06:25 +03:00
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
opt := opt
typ := typ
2020-08-15 11:41:38 +03:00
2020-12-25 10:06:25 +03:00
op := fmt.Sprintf(
"Struct%sField%s%s",
escapedOrNot,
opt,
typ,
)
opTypes = append(opTypes, opType{
2020-12-25 10:38:18 +03:00
Op: op,
Code: "StructField",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedField%sEscaped%s",
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedField%s%s",
opt,
typ,
)
},
2020-12-25 10:06:25 +03:00
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToOmitEmptyField: func() string {
return fmt.Sprintf(
"Struct%sFieldOmitEmpty%s",
escapedOrNot,
typ,
)
},
FieldToStringTagField: func() string {
return fmt.Sprintf(
"Struct%sFieldStringTag%s",
escapedOrNot,
typ,
)
},
})
}
}
2020-08-15 11:41:38 +03:00
}
2020-12-29 17:17:15 +03:00
for _, escapedOrNot := range []string{"", "Escaped"} {
for _, opt := range []string{"", "OmitEmpty", "StringTag"} {
for _, typ := range append(primitiveTypesUpper, "") {
escapedOrNot := escapedOrNot
opt := opt
typ := typ
op := fmt.Sprintf(
"Struct%sEnd%s%s",
escapedOrNot,
opt,
typ,
)
opTypes = append(opTypes, opType{
Op: op,
Code: "StructField",
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
Escaped: func() string {
switch typ {
case "String", "StringPtr", "StringNPtr":
return fmt.Sprintf(
"StructEscapedEnd%sEscaped%s",
opt,
typ,
)
}
return fmt.Sprintf(
"StructEscapedEnd%s%s",
opt,
typ,
)
},
HeadToPtrHead: func() string { return op },
HeadToNPtrHead: func() string { return op },
HeadToAnonymousHead: func() string { return op },
HeadToOmitEmptyHead: func() string { return op },
HeadToStringTagHead: func() string { return op },
PtrHeadToHead: func() string { return op },
FieldToOmitEmptyField: func() string {
return fmt.Sprintf(
"Struct%sEndOmitEmpty%s",
escapedOrNot,
typ,
)
},
FieldToStringTagField: func() string {
return fmt.Sprintf(
"Struct%sEndStringTag%s",
escapedOrNot,
typ,
)
},
})
}
}
}
2020-12-25 10:06:25 +03:00
indentOpTypes := []opType{}
for _, typ := range opTypes {
typ := typ
indentOpTypes = append(indentOpTypes, opType{
2020-12-25 10:38:18 +03:00
Op: fmt.Sprintf("%sIndent", typ.Op),
Code: typ.Code,
Indent: func() string { return fmt.Sprintf("%sIndent", typ.Op) },
Escaped: func() string { return fmt.Sprintf("%sIndent", typ.Escaped()) },
2020-12-25 10:06:25 +03:00
HeadToPtrHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToPtrHead())
},
HeadToNPtrHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToNPtrHead())
},
HeadToAnonymousHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToAnonymousHead())
},
HeadToOmitEmptyHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToOmitEmptyHead())
},
HeadToStringTagHead: func() string {
return fmt.Sprintf("%sIndent", typ.HeadToStringTagHead())
},
PtrHeadToHead: func() string {
return fmt.Sprintf("%sIndent", typ.PtrHeadToHead())
},
FieldToOmitEmptyField: func() string {
return fmt.Sprintf("%sIndent", typ.FieldToOmitEmptyField())
},
FieldToStringTagField: func() string {
return fmt.Sprintf("%sIndent", typ.FieldToStringTagField())
},
2020-08-15 11:41:38 +03:00
})
}
var b bytes.Buffer
if err := tmpl.Execute(&b, struct {
2020-12-25 10:06:25 +03:00
CodeTypes []string
OpTypes []opType
2020-08-15 11:41:38 +03:00
}{
2020-12-25 10:06:25 +03:00
CodeTypes: codeTypes,
OpTypes: append(opTypes, indentOpTypes...),
2020-08-15 11:41:38 +03:00
}); err != nil {
return err
}
path := filepath.Join(repoRoot(), "encode_optype.go")
2020-11-12 18:25:57 +03:00
buf, err := format.Source(b.Bytes())
if err != nil {
return err
}
return ioutil.WriteFile(path, buf, 0644)
2020-08-15 11:41:38 +03:00
}
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)
}
}