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) } }