Skip to content

Commit 92ed6c6

Browse files
authored
Merge pull request #25 from goccy/feature/support-anonymous-struct
Support embedded field
2 parents aa8099d + 876de76 commit 92ed6c6

File tree

6 files changed

+4798
-1653
lines changed

6 files changed

+4798
-1653
lines changed

cmd/generator/main.go

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io/ioutil"
7+
"path/filepath"
8+
"runtime"
9+
"strings"
10+
"text/template"
11+
)
12+
13+
type opType struct {
14+
Op string
15+
IndentOp string
16+
Code string
17+
}
18+
19+
type headType struct {
20+
Head string
21+
PtrHead string
22+
AnonymousHead string
23+
AnonymousPtrHead string
24+
OmitEmptyHead string
25+
OmitEmptyPtrHead string
26+
AnonymousOmitEmptyHead string
27+
AnonymousOmitEmptyPtrHead string
28+
}
29+
30+
type fieldType struct {
31+
Field string
32+
OmitEmptyField string
33+
}
34+
35+
func _main() error {
36+
tmpl, err := template.New("").Parse(`// Code generated by cmd/generator. DO NOT EDIT!
37+
package json
38+
39+
type codeType int
40+
41+
const (
42+
{{- range $index, $type := .CodeTypes }}
43+
code{{ $type }} codeType = {{ $index }}
44+
{{- end }}
45+
)
46+
47+
type opType int
48+
49+
const (
50+
{{- range $index, $type := .OpTypes }}
51+
op{{ $type.Op }} opType = {{ $index }}
52+
{{- end }}
53+
)
54+
55+
func (t opType) String() string {
56+
switch t {
57+
{{- range $type := .OpTypes }}
58+
case op{{ $type.Op }}:
59+
return "{{ $type.Op }}"
60+
{{- end }}
61+
}
62+
return ""
63+
}
64+
65+
func (t opType) codeType() codeType {
66+
switch t {
67+
{{- range $type := .OpTypes }}
68+
case op{{ $type.Op }}:
69+
return code{{ $type.Code }}
70+
{{- end }}
71+
}
72+
return codeOp
73+
}
74+
75+
func (t opType) toIndent() opType {
76+
switch t {
77+
{{- range $type := .OpTypes }}
78+
case op{{ $type.Op }}:
79+
return op{{ $type.IndentOp }}
80+
{{- end }}
81+
}
82+
return t
83+
}
84+
85+
func (t opType) headToPtrHead() opType {
86+
switch t {
87+
{{- range $type := .HeadTypes }}
88+
case op{{ $type.Head }}:
89+
return op{{ $type.PtrHead }}
90+
case op{{ $type.AnonymousHead }}:
91+
return op{{ $type.AnonymousPtrHead }}
92+
case op{{ $type.OmitEmptyHead }}:
93+
return op{{ $type.OmitEmptyPtrHead }}
94+
case op{{ $type.AnonymousOmitEmptyHead }}:
95+
return op{{ $type.AnonymousOmitEmptyPtrHead }}
96+
{{- end }}
97+
}
98+
return t
99+
}
100+
101+
func (t opType) headToAnonymousHead() opType {
102+
switch t {
103+
{{- range $type := .HeadTypes }}
104+
case op{{ $type.Head }}:
105+
return op{{ $type.AnonymousHead }}
106+
case op{{ $type.PtrHead }}:
107+
return op{{ $type.AnonymousPtrHead }}
108+
case op{{ $type.OmitEmptyHead }}:
109+
return op{{ $type.AnonymousOmitEmptyHead }}
110+
case op{{ $type.OmitEmptyPtrHead }}:
111+
return op{{ $type.AnonymousOmitEmptyPtrHead }}
112+
{{- end }}
113+
}
114+
return t
115+
}
116+
117+
func (t opType) headToOmitEmptyHead() opType {
118+
switch t {
119+
{{- range $type := .HeadTypes }}
120+
case op{{ $type.Head }}:
121+
return op{{ $type.OmitEmptyHead }}
122+
case op{{ $type.PtrHead }}:
123+
return op{{ $type.OmitEmptyPtrHead }}
124+
{{- end }}
125+
}
126+
return t
127+
}
128+
129+
func (t opType) ptrHeadToHead() opType {
130+
switch t {
131+
{{- range $type := .HeadTypes }}
132+
case op{{ $type.PtrHead }}:
133+
return op{{ $type.Head }}
134+
case op{{ $type.AnonymousPtrHead }}:
135+
return op{{ $type.AnonymousHead }}
136+
case op{{ $type.OmitEmptyPtrHead }}:
137+
return op{{ $type.OmitEmptyHead }}
138+
case op{{ $type.AnonymousOmitEmptyPtrHead }}:
139+
return op{{ $type.AnonymousOmitEmptyHead }}
140+
{{- end }}
141+
}
142+
return t
143+
}
144+
145+
func (t opType) fieldToOmitEmptyField() opType {
146+
switch t {
147+
{{- range $type := .FieldTypes }}
148+
case op{{ $type.Field }}:
149+
return op{{ $type.OmitEmptyField }}
150+
{{- end }}
151+
}
152+
return t
153+
}
154+
155+
`)
156+
if err != nil {
157+
return err
158+
}
159+
codeTypes := []string{
160+
"Op",
161+
"ArrayHead",
162+
"ArrayElem",
163+
"SliceHead",
164+
"SliceElem",
165+
"MapHead",
166+
"MapKey",
167+
"MapValue",
168+
"StructFieldRecursive",
169+
"StructField",
170+
}
171+
primitiveTypes := []string{
172+
"int", "int8", "int16", "int32", "int64",
173+
"uint", "uint8", "uint16", "uint32", "uint64",
174+
"float32", "float64", "bool", "string",
175+
}
176+
primitiveTypesUpper := []string{}
177+
for _, typ := range primitiveTypes {
178+
primitiveTypesUpper = append(primitiveTypesUpper, strings.ToUpper(string(typ[0]))+typ[1:])
179+
}
180+
opTypes := []opType{
181+
{"End", "EndIndent", "Op"},
182+
{"Interface", "InterfaceIndent", "Op"},
183+
{"Ptr", "PtrIndent", "Op"},
184+
{"MarshalJSON", "MarshalJSONIndent", "Op"},
185+
{"MarshalText", "MarshalTextIndent", "Op"},
186+
{"SliceHead", "SliceHeadIndent", "SliceHead"},
187+
{"RootSliceHead", "RootSliceHeadIndent", "SliceHead"},
188+
{"SliceElem", "SliceElemIndent", "SliceElem"},
189+
{"RootSliceElem", "RootSliceElemIndent", "SliceElem"},
190+
{"SliceEnd", "SliceEndIndent", "Op"},
191+
{"ArrayHead", "ArrayHeadIndent", "ArrayHead"},
192+
{"ArrayElem", "ArrayElemIndent", "ArrayElem"},
193+
{"ArrayEnd", "ArrayEndIndent", "Op"},
194+
{"MapHead", "MapHeadIndent", "MapHead"},
195+
{"MapHeadLoad", "MapHeadLoadIndent", "MapHead"},
196+
{"RootMapHead", "RootMapHeadIndent", "MapHead"},
197+
{"MapKey", "MapKeyIndent", "MapKey"},
198+
{"RootMapKey", "RootMapKeyIndent", "MapKey"},
199+
{"MapValue", "MapValueIndent", "MapValue"},
200+
{"MapEnd", "MapEndIndent", "Op"},
201+
{"StructFieldHead", "StructFieldHeadIndent", "StructField"},
202+
{"StructFieldHeadOmitEmpty", "StructFieldHeadOmitEmptyIndent", "StructField"},
203+
{"StructFieldAnonymousHead", "StructFieldAnonymousHeadIndent", "StructField"},
204+
{"StructFieldAnonymousHeadOmitEmpty", "StructFieldAnonymousHeadOmitEmptyIndent", "StructField"},
205+
{"StructFieldPtrAnonymousHeadOmitEmpty", "StructFieldPtrAnonymousHeadOmitEmptyIndent", "StructField"},
206+
{"StructFieldPtrHead", "StructFieldPtrHeadIndent", "StructField"},
207+
{"StructFieldPtrHeadOmitEmpty", "StructFieldPtrHeadOmitEmptyIndent", "StructField"},
208+
{"StructFieldPtrAnonymousHead", "StructFieldPtrAnonymousHeadIndent", "StructField"},
209+
{"StructField", "StructFieldIndent", "StructField"},
210+
{"StructFieldOmitEmpty", "StructFieldOmitEmptyIndent", "StructField"},
211+
{"StructFieldRecursive", "StructFieldRecursiveIndent", "StructFieldRecursive"},
212+
{"StructEnd", "StructEndIndent", "StructField"},
213+
{"StructAnonymousEnd", "StructAnonymousEndIndent", "StructField"},
214+
}
215+
for _, typ := range primitiveTypesUpper {
216+
opTypes = append(opTypes, opType{
217+
Op: typ,
218+
IndentOp: fmt.Sprintf("%sIndent", typ),
219+
Code: "Op",
220+
})
221+
}
222+
for _, prefix := range []string{
223+
"StructFieldHead",
224+
"StructFieldHeadOmitEmpty",
225+
"StructFieldAnonymousHead",
226+
"StructFieldAnonymousHeadOmitEmpty",
227+
"StructFieldPtrHead",
228+
"StructFieldPtrHeadOmitEmpty",
229+
"StructFieldPtrAnonymousHead",
230+
"StructFieldPtrAnonymousHeadOmitEmpty",
231+
"StructField",
232+
"StructFieldOmitEmpty",
233+
} {
234+
for _, typ := range primitiveTypesUpper {
235+
opTypes = append(opTypes, opType{
236+
Op: fmt.Sprintf("%s%s", prefix, typ),
237+
IndentOp: fmt.Sprintf("%s%sIndent", prefix, typ),
238+
Code: "StructField",
239+
})
240+
}
241+
}
242+
for _, typ := range opTypes {
243+
opTypes = append(opTypes, opType{
244+
Op: typ.IndentOp,
245+
IndentOp: typ.IndentOp,
246+
Code: typ.Code,
247+
})
248+
}
249+
base := headType{
250+
Head: "StructFieldHead",
251+
PtrHead: "StructFieldPtrHead",
252+
AnonymousHead: "StructFieldAnonymousHead",
253+
AnonymousPtrHead: "StructFieldPtrAnonymousHead",
254+
OmitEmptyHead: "StructFieldHeadOmitEmpty",
255+
OmitEmptyPtrHead: "StructFieldPtrHeadOmitEmpty",
256+
AnonymousOmitEmptyHead: "StructFieldAnonymousHeadOmitEmpty",
257+
AnonymousOmitEmptyPtrHead: "StructFieldPtrAnonymousHeadOmitEmpty",
258+
}
259+
headTypes := []headType{base}
260+
for _, prim := range primitiveTypesUpper {
261+
headTypes = append(headTypes, headType{
262+
Head: fmt.Sprintf("%s%s", base.Head, prim),
263+
PtrHead: fmt.Sprintf("%s%s", base.PtrHead, prim),
264+
AnonymousHead: fmt.Sprintf("%s%s", base.AnonymousHead, prim),
265+
AnonymousPtrHead: fmt.Sprintf("%s%s", base.AnonymousPtrHead, prim),
266+
OmitEmptyHead: fmt.Sprintf("%s%s", base.OmitEmptyHead, prim),
267+
OmitEmptyPtrHead: fmt.Sprintf("%s%s", base.OmitEmptyPtrHead, prim),
268+
AnonymousOmitEmptyHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyHead, prim),
269+
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%s%s", base.AnonymousOmitEmptyPtrHead, prim),
270+
})
271+
}
272+
for _, typ := range headTypes {
273+
headTypes = append(headTypes, headType{
274+
Head: fmt.Sprintf("%sIndent", typ.Head),
275+
PtrHead: fmt.Sprintf("%sIndent", typ.PtrHead),
276+
AnonymousHead: fmt.Sprintf("%sIndent", typ.AnonymousHead),
277+
AnonymousPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousPtrHead),
278+
OmitEmptyHead: fmt.Sprintf("%sIndent", typ.OmitEmptyHead),
279+
OmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.OmitEmptyPtrHead),
280+
AnonymousOmitEmptyHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyHead),
281+
AnonymousOmitEmptyPtrHead: fmt.Sprintf("%sIndent", typ.AnonymousOmitEmptyPtrHead),
282+
})
283+
}
284+
285+
baseField := fieldType{
286+
Field: "StructField",
287+
OmitEmptyField: "StructFieldOmitEmpty",
288+
}
289+
fieldTypes := []fieldType{baseField}
290+
for _, prim := range primitiveTypesUpper {
291+
fieldTypes = append(fieldTypes, fieldType{
292+
Field: fmt.Sprintf("%s%s", baseField.Field, prim),
293+
OmitEmptyField: fmt.Sprintf("%s%s", baseField.OmitEmptyField, prim),
294+
})
295+
}
296+
for _, typ := range fieldTypes {
297+
fieldTypes = append(fieldTypes, fieldType{
298+
Field: fmt.Sprintf("%sIndent", typ.Field),
299+
OmitEmptyField: fmt.Sprintf("%sIndent", typ.OmitEmptyField),
300+
})
301+
}
302+
303+
var b bytes.Buffer
304+
if err := tmpl.Execute(&b, struct {
305+
CodeTypes []string
306+
OpTypes []opType
307+
HeadTypes []headType
308+
FieldTypes []fieldType
309+
}{
310+
CodeTypes: codeTypes,
311+
OpTypes: opTypes,
312+
HeadTypes: headTypes,
313+
FieldTypes: fieldTypes,
314+
}); err != nil {
315+
return err
316+
}
317+
path := filepath.Join(repoRoot(), "encode_optype.go")
318+
return ioutil.WriteFile(path, b.Bytes(), 0644)
319+
}
320+
321+
func repoRoot() string {
322+
_, file, _, _ := runtime.Caller(0)
323+
relativePathFromRepoRoot := filepath.Join("cmd", "generator")
324+
return strings.TrimSuffix(filepath.Dir(file), relativePathFromRepoRoot)
325+
}
326+
327+
func main() {
328+
if err := _main(); err != nil {
329+
panic(err)
330+
}
331+
}

0 commit comments

Comments
 (0)