forked from mirror/go-json
478 lines
12 KiB
Go
478 lines
12 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"go/format"
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
type opType struct {
|
|
Op string
|
|
Code string
|
|
Indent func() string
|
|
Escaped func() string
|
|
HeadToPtrHead func() string
|
|
HeadToNPtrHead func() string
|
|
HeadToAnonymousHead func() string
|
|
HeadToOmitEmptyHead func() string
|
|
HeadToStringTagHead func() string
|
|
PtrHeadToHead func() string
|
|
FieldToOmitEmptyField func() string
|
|
FieldToStringTagField func() string
|
|
}
|
|
|
|
func createOpType(op, code string) opType {
|
|
return opType{
|
|
Op: op,
|
|
Code: code,
|
|
Indent: func() string { return fmt.Sprintf("%sIndent", op) },
|
|
Escaped: func() string { return op },
|
|
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 },
|
|
}
|
|
}
|
|
|
|
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{{ call $type.Indent }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) toEscaped() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.Escaped }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) headToPtrHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.HeadToPtrHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) headToNPtrHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.HeadToNPtrHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) headToAnonymousHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.HeadToAnonymousHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) headToOmitEmptyHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.HeadToOmitEmptyHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) headToStringTagHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.HeadToStringTagHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) ptrHeadToHead() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.PtrHeadToHead }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) fieldToOmitEmptyField() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.FieldToOmitEmptyField }}
|
|
{{- end }}
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t opType) fieldToStringTagField() opType {
|
|
switch t {
|
|
{{- range $type := .OpTypes }}
|
|
case op{{ $type.Op }}:
|
|
return op{{ call $type.FieldToStringTagField }}
|
|
{{- 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", "escapedString", "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", "escapedStringPtr", "bytesPtr",
|
|
"intNPtr", "int8NPtr", "int16NPtr", "int32NPtr", "int64NPtr",
|
|
"uintNPtr", "uint8NPtr", "uint16NPtr", "uint32NPtr", "uint64NPtr",
|
|
"float32NPtr", "float64NPtr", "boolNPtr", "stringNPtr", "escapedStringNPtr", "bytesNPtr",
|
|
}
|
|
primitiveTypesUpper := []string{}
|
|
for _, typ := range primitiveTypes {
|
|
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
|
|
}
|
|
opTypes := []opType{
|
|
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("StructEnd", "StructField"),
|
|
createOpType("StructAnonymousEnd", "StructField"),
|
|
}
|
|
for _, typ := range primitiveTypesUpper {
|
|
typ := typ
|
|
optype := createOpType(typ, "Op")
|
|
switch typ {
|
|
case "String", "StringPtr", "StringNPtr":
|
|
optype.Escaped = func() string {
|
|
return fmt.Sprintf("Escaped%s", typ)
|
|
}
|
|
}
|
|
opTypes = append(opTypes, optype)
|
|
}
|
|
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) },
|
|
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,
|
|
)
|
|
},
|
|
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 },
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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%sField%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(
|
|
"StructEscapedField%sEscaped%s",
|
|
opt,
|
|
typ,
|
|
)
|
|
}
|
|
return fmt.Sprintf(
|
|
"StructEscapedField%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%sFieldOmitEmpty%s",
|
|
escapedOrNot,
|
|
typ,
|
|
)
|
|
},
|
|
FieldToStringTagField: func() string {
|
|
return fmt.Sprintf(
|
|
"Struct%sFieldStringTag%s",
|
|
escapedOrNot,
|
|
typ,
|
|
)
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
indentOpTypes := []opType{}
|
|
for _, typ := range opTypes {
|
|
typ := typ
|
|
indentOpTypes = append(indentOpTypes, opType{
|
|
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()) },
|
|
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())
|
|
},
|
|
})
|
|
}
|
|
var b bytes.Buffer
|
|
if err := tmpl.Execute(&b, struct {
|
|
CodeTypes []string
|
|
OpTypes []opType
|
|
}{
|
|
CodeTypes: codeTypes,
|
|
OpTypes: append(opTypes, indentOpTypes...),
|
|
}); 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)
|
|
}
|
|
}
|