forked from mirror/go-json
402 lines
12 KiB
Go
402 lines
12 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
|
|
AnonymousHead string
|
|
AnonymousPtrHead string
|
|
OmitEmptyHead string
|
|
OmitEmptyPtrHead string
|
|
AnonymousOmitEmptyHead string
|
|
AnonymousOmitEmptyPtrHead string
|
|
StringTagHead string
|
|
StringTagPtrHead string
|
|
AnonymousStringTagHead string
|
|
AnonymousStringTagPtrHead 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) 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 }}:
|
|
return op{{ $type.Head }}
|
|
case op{{ $type.AnonymousPtrHead }}:
|
|
return op{{ $type.AnonymousHead }}
|
|
case op{{ $type.OmitEmptyPtrHead }}:
|
|
return op{{ $type.OmitEmptyHead }}
|
|
case op{{ $type.AnonymousOmitEmptyPtrHead }}:
|
|
return op{{ $type.AnonymousOmitEmptyHead }}
|
|
case op{{ $type.StringTagPtrHead }}:
|
|
return op{{ $type.StringTagHead }}
|
|
case op{{ $type.AnonymousStringTagPtrHead }}:
|
|
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",
|
|
}
|
|
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"},
|
|
{"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"},
|
|
{"StructFieldAnonymousHeadStringTag", "StructFieldAnonymousHeadStringTagIndent", "StructField"},
|
|
{"StructFieldPtrAnonymousHeadStringTag", "StructFieldPtrAnonymousHeadStringTagIndent", "StructField"},
|
|
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
|
|
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
|
|
{"StructFieldPtrHeadStringTag", "StructFieldPtrHeadStringTagIndent", "StructField"},
|
|
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
|
|
{"StructField", "StructFieldIndent", "StructField"},
|
|
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
|
|
{"StructFieldStringTag", "StructFieldStringTagIndent", "StructField"},
|
|
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
|
|
{"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",
|
|
"StructField",
|
|
"StructFieldPtr",
|
|
"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",
|
|
AnonymousHead: "StructFieldAnonymousHead",
|
|
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
|
|
OmitEmptyHead: "StructFieldHeadOmitEmpty",
|
|
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
|
|
StringTagHead: "StructFieldHeadStringTag",
|
|
StringTagPtrHead: "StructFieldPtrHeadStringTag",
|
|
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
|
|
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
|
|
AnonymousStringTagHead: "StructFieldAnonymousHeadStringTag",
|
|
AnonymousStringTagPtrHead: "StructFieldPtrAnonymousHeadStringTag",
|
|
}
|
|
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),
|
|
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
|
|
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
|
|
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
|
|
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
|
|
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
|
|
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
|
|
StringTagHead: fmt.Sprintf("%s%s", base.StringTagHead, prim),
|
|
StringTagPtrHead: fmt.Sprintf("%s%s", base.StringTagPtrHead, prim),
|
|
AnonymousStringTagHead: fmt.Sprintf("%s%s", base.AnonymousStringTagHead, prim),
|
|
AnonymousStringTagPtrHead: fmt.Sprintf("%s%s", base.AnonymousStringTagPtrHead, prim),
|
|
})
|
|
}
|
|
for _, typ := range headTypes {
|
|
headTypes = append(headTypes, headType{
|
|
Head: fmt.Sprintf("%sIndent", typ.Head),
|
|
PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead),
|
|
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
|
|
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
|
|
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
|
|
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
|
|
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
|
|
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
|
|
StringTagHead: fmt.Sprintf("%sIndent", typ.StringTagHead),
|
|
StringTagPtrHead: fmt.Sprintf("%sIndent", typ.StringTagPtrHead),
|
|
AnonymousStringTagHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagHead),
|
|
AnonymousStringTagPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousStringTagPtrHead),
|
|
})
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|