1 package gen
2
3 import (
4 "encoding"
5 "encoding/json"
6 "errors"
7 "fmt"
8 "reflect"
9 "strings"
10 "unicode"
11
12 "github.com/mailru/easyjson"
13 )
14
15
16 const minSliceBytes = 64
17
18 func (g *Generator) getDecoderName(t reflect.Type) string {
19 return g.functionName("decode", t)
20 }
21
22 var primitiveDecoders = map[reflect.Kind]string{
23 reflect.String: "in.String()",
24 reflect.Bool: "in.Bool()",
25 reflect.Int: "in.Int()",
26 reflect.Int8: "in.Int8()",
27 reflect.Int16: "in.Int16()",
28 reflect.Int32: "in.Int32()",
29 reflect.Int64: "in.Int64()",
30 reflect.Uint: "in.Uint()",
31 reflect.Uint8: "in.Uint8()",
32 reflect.Uint16: "in.Uint16()",
33 reflect.Uint32: "in.Uint32()",
34 reflect.Uint64: "in.Uint64()",
35 reflect.Float32: "in.Float32()",
36 reflect.Float64: "in.Float64()",
37 }
38
39 var primitiveStringDecoders = map[reflect.Kind]string{
40 reflect.String: "in.String()",
41 reflect.Int: "in.IntStr()",
42 reflect.Int8: "in.Int8Str()",
43 reflect.Int16: "in.Int16Str()",
44 reflect.Int32: "in.Int32Str()",
45 reflect.Int64: "in.Int64Str()",
46 reflect.Uint: "in.UintStr()",
47 reflect.Uint8: "in.Uint8Str()",
48 reflect.Uint16: "in.Uint16Str()",
49 reflect.Uint32: "in.Uint32Str()",
50 reflect.Uint64: "in.Uint64Str()",
51 reflect.Uintptr: "in.UintptrStr()",
52 reflect.Float32: "in.Float32Str()",
53 reflect.Float64: "in.Float64Str()",
54 }
55
56 var customDecoders = map[string]string{
57 "json.Number": "in.JsonNumber()",
58 }
59
60
61 func (g *Generator) genTypeDecoder(t reflect.Type, out string, tags fieldTags, indent int) error {
62 ws := strings.Repeat(" ", indent)
63
64 unmarshalerIface := reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem()
65 if reflect.PtrTo(t).Implements(unmarshalerIface) {
66 fmt.Fprintln(g.out, ws+"("+out+").UnmarshalEasyJSON(in)")
67 return nil
68 }
69
70 unmarshalerIface = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
71 if reflect.PtrTo(t).Implements(unmarshalerIface) {
72 fmt.Fprintln(g.out, ws+"if data := in.Raw(); in.Ok() {")
73 fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalJSON(data) )")
74 fmt.Fprintln(g.out, ws+"}")
75 return nil
76 }
77
78 unmarshalerIface = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
79 if reflect.PtrTo(t).Implements(unmarshalerIface) {
80 fmt.Fprintln(g.out, ws+"if data := in.UnsafeBytes(); in.Ok() {")
81 fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalText(data) )")
82 fmt.Fprintln(g.out, ws+"}")
83 return nil
84 }
85
86 err := g.genTypeDecoderNoCheck(t, out, tags, indent)
87 return err
88 }
89
90
91 func hasCustomUnmarshaler(t reflect.Type) bool {
92 t = reflect.PtrTo(t)
93 return t.Implements(reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem()) ||
94 t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()) ||
95 t.Implements(reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem())
96 }
97
98 func hasUnknownsUnmarshaler(t reflect.Type) bool {
99 t = reflect.PtrTo(t)
100 return t.Implements(reflect.TypeOf((*easyjson.UnknownsUnmarshaler)(nil)).Elem())
101 }
102
103 func hasUnknownsMarshaler(t reflect.Type) bool {
104 t = reflect.PtrTo(t)
105 return t.Implements(reflect.TypeOf((*easyjson.UnknownsMarshaler)(nil)).Elem())
106 }
107
108
109 func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags fieldTags, indent int) error {
110 ws := strings.Repeat(" ", indent)
111
112 if dec := customDecoders[t.String()]; dec != "" {
113 fmt.Fprintln(g.out, ws+out+" = "+dec)
114 return nil
115 } else if dec := primitiveStringDecoders[t.Kind()]; dec != "" && tags.asString {
116 if tags.intern && t.Kind() == reflect.String {
117 dec = "in.StringIntern()"
118 }
119 fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
120 return nil
121 } else if dec := primitiveDecoders[t.Kind()]; dec != "" {
122 if tags.intern && t.Kind() == reflect.String {
123 dec = "in.StringIntern()"
124 }
125 if tags.noCopy && t.Kind() == reflect.String {
126 dec = "in.UnsafeString()"
127 }
128 fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
129 return nil
130 }
131
132 switch t.Kind() {
133 case reflect.Slice:
134 tmpVar := g.uniqueVarName()
135 elem := t.Elem()
136
137 if elem.Kind() == reflect.Uint8 && elem.Name() == "uint8" {
138 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
139 fmt.Fprintln(g.out, ws+" in.Skip()")
140 fmt.Fprintln(g.out, ws+" "+out+" = nil")
141 fmt.Fprintln(g.out, ws+"} else {")
142 if g.simpleBytes {
143 fmt.Fprintln(g.out, ws+" "+out+" = []byte(in.String())")
144 } else {
145 fmt.Fprintln(g.out, ws+" "+out+" = in.Bytes()")
146 }
147
148 fmt.Fprintln(g.out, ws+"}")
149
150 } else {
151
152 capacity := 1
153 if elem.Size() > 0 {
154 capacity = minSliceBytes / int(elem.Size())
155 }
156
157 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
158 fmt.Fprintln(g.out, ws+" in.Skip()")
159 fmt.Fprintln(g.out, ws+" "+out+" = nil")
160 fmt.Fprintln(g.out, ws+"} else {")
161 fmt.Fprintln(g.out, ws+" in.Delim('[')")
162 fmt.Fprintln(g.out, ws+" if "+out+" == nil {")
163 fmt.Fprintln(g.out, ws+" if !in.IsDelim(']') {")
164 fmt.Fprintln(g.out, ws+" "+out+" = make("+g.getType(t)+", 0, "+fmt.Sprint(capacity)+")")
165 fmt.Fprintln(g.out, ws+" } else {")
166 fmt.Fprintln(g.out, ws+" "+out+" = "+g.getType(t)+"{}")
167 fmt.Fprintln(g.out, ws+" }")
168 fmt.Fprintln(g.out, ws+" } else { ")
169 fmt.Fprintln(g.out, ws+" "+out+" = ("+out+")[:0]")
170 fmt.Fprintln(g.out, ws+" }")
171 fmt.Fprintln(g.out, ws+" for !in.IsDelim(']') {")
172 fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
173
174 if err := g.genTypeDecoder(elem, tmpVar, tags, indent+2); err != nil {
175 return err
176 }
177
178 fmt.Fprintln(g.out, ws+" "+out+" = append("+out+", "+tmpVar+")")
179 fmt.Fprintln(g.out, ws+" in.WantComma()")
180 fmt.Fprintln(g.out, ws+" }")
181 fmt.Fprintln(g.out, ws+" in.Delim(']')")
182 fmt.Fprintln(g.out, ws+"}")
183 }
184
185 case reflect.Array:
186 iterVar := g.uniqueVarName()
187 elem := t.Elem()
188
189 if elem.Kind() == reflect.Uint8 && elem.Name() == "uint8" {
190 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
191 fmt.Fprintln(g.out, ws+" in.Skip()")
192 fmt.Fprintln(g.out, ws+"} else {")
193 fmt.Fprintln(g.out, ws+" copy("+out+"[:], in.Bytes())")
194 fmt.Fprintln(g.out, ws+"}")
195
196 } else {
197
198 length := t.Len()
199
200 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
201 fmt.Fprintln(g.out, ws+" in.Skip()")
202 fmt.Fprintln(g.out, ws+"} else {")
203 fmt.Fprintln(g.out, ws+" in.Delim('[')")
204 fmt.Fprintln(g.out, ws+" "+iterVar+" := 0")
205 fmt.Fprintln(g.out, ws+" for !in.IsDelim(']') {")
206 fmt.Fprintln(g.out, ws+" if "+iterVar+" < "+fmt.Sprint(length)+" {")
207
208 if err := g.genTypeDecoder(elem, "("+out+")["+iterVar+"]", tags, indent+3); err != nil {
209 return err
210 }
211
212 fmt.Fprintln(g.out, ws+" "+iterVar+"++")
213 fmt.Fprintln(g.out, ws+" } else {")
214 fmt.Fprintln(g.out, ws+" in.SkipRecursive()")
215 fmt.Fprintln(g.out, ws+" }")
216 fmt.Fprintln(g.out, ws+" in.WantComma()")
217 fmt.Fprintln(g.out, ws+" }")
218 fmt.Fprintln(g.out, ws+" in.Delim(']')")
219 fmt.Fprintln(g.out, ws+"}")
220 }
221
222 case reflect.Struct:
223 dec := g.getDecoderName(t)
224 g.addType(t)
225
226 if len(out) > 0 && out[0] == '*' {
227
228 fmt.Fprintln(g.out, ws+dec+"(in, "+out[1:]+")")
229 } else {
230 fmt.Fprintln(g.out, ws+dec+"(in, &"+out+")")
231 }
232
233 case reflect.Ptr:
234 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
235 fmt.Fprintln(g.out, ws+" in.Skip()")
236 fmt.Fprintln(g.out, ws+" "+out+" = nil")
237 fmt.Fprintln(g.out, ws+"} else {")
238 fmt.Fprintln(g.out, ws+" if "+out+" == nil {")
239 fmt.Fprintln(g.out, ws+" "+out+" = new("+g.getType(t.Elem())+")")
240 fmt.Fprintln(g.out, ws+" }")
241
242 if err := g.genTypeDecoder(t.Elem(), "*"+out, tags, indent+1); err != nil {
243 return err
244 }
245
246 fmt.Fprintln(g.out, ws+"}")
247
248 case reflect.Map:
249 key := t.Key()
250 keyDec, ok := primitiveStringDecoders[key.Kind()]
251 if !ok && !hasCustomUnmarshaler(key) {
252 return fmt.Errorf("map type %v not supported: only string and integer keys and types implementing json.Unmarshaler are allowed", key)
253 }
254 elem := t.Elem()
255 tmpVar := g.uniqueVarName()
256 keepEmpty := tags.required || tags.noOmitEmpty || (!g.omitEmpty && !tags.omitEmpty)
257
258 fmt.Fprintln(g.out, ws+"if in.IsNull() {")
259 fmt.Fprintln(g.out, ws+" in.Skip()")
260 fmt.Fprintln(g.out, ws+"} else {")
261 fmt.Fprintln(g.out, ws+" in.Delim('{')")
262 if !keepEmpty {
263 fmt.Fprintln(g.out, ws+" if !in.IsDelim('}') {")
264 }
265 fmt.Fprintln(g.out, ws+" "+out+" = make("+g.getType(t)+")")
266 if !keepEmpty {
267 fmt.Fprintln(g.out, ws+" } else {")
268 fmt.Fprintln(g.out, ws+" "+out+" = nil")
269 fmt.Fprintln(g.out, ws+" }")
270 }
271
272 fmt.Fprintln(g.out, ws+" for !in.IsDelim('}') {")
273
274 if reflect.PtrTo(key).Implements(reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()) {
275 fmt.Fprintln(g.out, ws+" var key "+g.getType(key))
276 fmt.Fprintln(g.out, ws+"if data := in.UnsafeBytes(); in.Ok() {")
277 fmt.Fprintln(g.out, ws+" in.AddError(key.UnmarshalText(data) )")
278 fmt.Fprintln(g.out, ws+"}")
279 } else if keyDec != "" {
280 fmt.Fprintln(g.out, ws+" key := "+g.getType(key)+"("+keyDec+")")
281 } else {
282 fmt.Fprintln(g.out, ws+" var key "+g.getType(key))
283 if err := g.genTypeDecoder(key, "key", tags, indent+2); err != nil {
284 return err
285 }
286 }
287
288 fmt.Fprintln(g.out, ws+" in.WantColon()")
289 fmt.Fprintln(g.out, ws+" var "+tmpVar+" "+g.getType(elem))
290
291 if err := g.genTypeDecoder(elem, tmpVar, tags, indent+2); err != nil {
292 return err
293 }
294
295 fmt.Fprintln(g.out, ws+" ("+out+")[key] = "+tmpVar)
296 fmt.Fprintln(g.out, ws+" in.WantComma()")
297 fmt.Fprintln(g.out, ws+" }")
298 fmt.Fprintln(g.out, ws+" in.Delim('}')")
299 fmt.Fprintln(g.out, ws+"}")
300
301 case reflect.Interface:
302 if t.NumMethod() != 0 {
303 if g.interfaceIsEasyjsonUnmarshaller(t) {
304 fmt.Fprintln(g.out, ws+out+".UnmarshalEasyJSON(in)")
305 } else if g.interfaceIsJsonUnmarshaller(t) {
306 fmt.Fprintln(g.out, ws+out+".UnmarshalJSON(in.Raw())")
307 } else {
308 return fmt.Errorf("interface type %v not supported: only interface{} and easyjson/json Unmarshaler are allowed", t)
309 }
310 } else {
311 fmt.Fprintln(g.out, ws+"if m, ok := "+out+".(easyjson.Unmarshaler); ok {")
312 fmt.Fprintln(g.out, ws+"m.UnmarshalEasyJSON(in)")
313 fmt.Fprintln(g.out, ws+"} else if m, ok := "+out+".(json.Unmarshaler); ok {")
314 fmt.Fprintln(g.out, ws+"_ = m.UnmarshalJSON(in.Raw())")
315 fmt.Fprintln(g.out, ws+"} else {")
316 fmt.Fprintln(g.out, ws+" "+out+" = in.Interface()")
317 fmt.Fprintln(g.out, ws+"}")
318 }
319 default:
320 return fmt.Errorf("don't know how to decode %v", t)
321 }
322 return nil
323
324 }
325
326 func (g *Generator) interfaceIsEasyjsonUnmarshaller(t reflect.Type) bool {
327 return t.Implements(reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem())
328 }
329
330 func (g *Generator) interfaceIsJsonUnmarshaller(t reflect.Type) bool {
331 return t.Implements(reflect.TypeOf((*json.Unmarshaler)(nil)).Elem())
332 }
333
334 func (g *Generator) genStructFieldDecoder(t reflect.Type, f reflect.StructField) error {
335 jsonName := g.fieldNamer.GetJSONFieldName(t, f)
336 tags := parseFieldTags(f)
337
338 if tags.omit {
339 return nil
340 }
341 if tags.intern && tags.noCopy {
342 return errors.New("Mutually exclusive tags are specified: 'intern' and 'nocopy'")
343 }
344
345 fmt.Fprintf(g.out, " case %q:\n", jsonName)
346 if err := g.genTypeDecoder(f.Type, "out."+f.Name, tags, 3); err != nil {
347 return err
348 }
349
350 if tags.required {
351 fmt.Fprintf(g.out, "%sSet = true\n", f.Name)
352 }
353
354 return nil
355 }
356
357 func (g *Generator) genRequiredFieldSet(t reflect.Type, f reflect.StructField) {
358 tags := parseFieldTags(f)
359
360 if !tags.required {
361 return
362 }
363
364 fmt.Fprintf(g.out, "var %sSet bool\n", f.Name)
365 }
366
367 func (g *Generator) genRequiredFieldCheck(t reflect.Type, f reflect.StructField) {
368 jsonName := g.fieldNamer.GetJSONFieldName(t, f)
369 tags := parseFieldTags(f)
370
371 if !tags.required {
372 return
373 }
374
375 g.imports["fmt"] = "fmt"
376
377 fmt.Fprintf(g.out, "if !%sSet {\n", f.Name)
378 fmt.Fprintf(g.out, " in.AddError(fmt.Errorf(\"key '%s' is required\"))\n", jsonName)
379 fmt.Fprintf(g.out, "}\n")
380 }
381
382 func mergeStructFields(fields1, fields2 []reflect.StructField) (fields []reflect.StructField) {
383 used := map[string]bool{}
384 for _, f := range fields2 {
385 used[f.Name] = true
386 fields = append(fields, f)
387 }
388
389 for _, f := range fields1 {
390 if !used[f.Name] {
391 fields = append(fields, f)
392 }
393 }
394 return
395 }
396
397 func getStructFields(t reflect.Type) ([]reflect.StructField, error) {
398 if t.Kind() != reflect.Struct {
399 return nil, fmt.Errorf("got %v; expected a struct", t)
400 }
401
402 var efields []reflect.StructField
403 var fields []reflect.StructField
404 for i := 0; i < t.NumField(); i++ {
405 f := t.Field(i)
406 tags := parseFieldTags(f)
407 if !f.Anonymous || tags.name != "" {
408 continue
409 }
410
411 t1 := f.Type
412 if t1.Kind() == reflect.Ptr {
413 t1 = t1.Elem()
414 }
415
416 if t1.Kind() == reflect.Struct {
417 fs, err := getStructFields(t1)
418 if err != nil {
419 return nil, fmt.Errorf("error processing embedded field: %v", err)
420 }
421 efields = mergeStructFields(efields, fs)
422 } else if (t1.Kind() >= reflect.Bool && t1.Kind() < reflect.Complex128) || t1.Kind() == reflect.String {
423 if strings.Contains(f.Name, ".") || unicode.IsUpper([]rune(f.Name)[0]) {
424 fields = append(fields, f)
425 }
426 }
427 }
428
429 for i := 0; i < t.NumField(); i++ {
430 f := t.Field(i)
431 tags := parseFieldTags(f)
432 if f.Anonymous && tags.name == "" {
433 continue
434 }
435
436 c := []rune(f.Name)[0]
437 if unicode.IsUpper(c) {
438 fields = append(fields, f)
439 }
440 }
441 return mergeStructFields(efields, fields), nil
442 }
443
444 func (g *Generator) genDecoder(t reflect.Type) error {
445 switch t.Kind() {
446 case reflect.Slice, reflect.Array, reflect.Map:
447 return g.genSliceArrayDecoder(t)
448 default:
449 return g.genStructDecoder(t)
450 }
451 }
452
453 func (g *Generator) genSliceArrayDecoder(t reflect.Type) error {
454 switch t.Kind() {
455 case reflect.Slice, reflect.Array, reflect.Map:
456 default:
457 return fmt.Errorf("cannot generate encoder/decoder for %v, not a slice/array/map type", t)
458 }
459
460 fname := g.getDecoderName(t)
461 typ := g.getType(t)
462
463 fmt.Fprintln(g.out, "func "+fname+"(in *jlexer.Lexer, out *"+typ+") {")
464 fmt.Fprintln(g.out, " isTopLevel := in.IsStart()")
465 err := g.genTypeDecoderNoCheck(t, "*out", fieldTags{}, 1)
466 if err != nil {
467 return err
468 }
469 fmt.Fprintln(g.out, " if isTopLevel {")
470 fmt.Fprintln(g.out, " in.Consumed()")
471 fmt.Fprintln(g.out, " }")
472 fmt.Fprintln(g.out, "}")
473
474 return nil
475 }
476
477 func (g *Generator) genStructDecoder(t reflect.Type) error {
478 if t.Kind() != reflect.Struct {
479 return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct type", t)
480 }
481
482 fname := g.getDecoderName(t)
483 typ := g.getType(t)
484
485 fmt.Fprintln(g.out, "func "+fname+"(in *jlexer.Lexer, out *"+typ+") {")
486 fmt.Fprintln(g.out, " isTopLevel := in.IsStart()")
487 fmt.Fprintln(g.out, " if in.IsNull() {")
488 fmt.Fprintln(g.out, " if isTopLevel {")
489 fmt.Fprintln(g.out, " in.Consumed()")
490 fmt.Fprintln(g.out, " }")
491 fmt.Fprintln(g.out, " in.Skip()")
492 fmt.Fprintln(g.out, " return")
493 fmt.Fprintln(g.out, " }")
494
495
496 for i := 0; i < t.NumField(); i++ {
497 f := t.Field(i)
498 if !f.Anonymous || f.Type.Kind() != reflect.Ptr {
499 continue
500 }
501 fmt.Fprintln(g.out, " out."+f.Name+" = new("+g.getType(f.Type.Elem())+")")
502 }
503
504 fs, err := getStructFields(t)
505 if err != nil {
506 return fmt.Errorf("cannot generate decoder for %v: %v", t, err)
507 }
508
509 for _, f := range fs {
510 g.genRequiredFieldSet(t, f)
511 }
512
513 fmt.Fprintln(g.out, " in.Delim('{')")
514 fmt.Fprintln(g.out, " for !in.IsDelim('}') {")
515 fmt.Fprintf(g.out, " key := in.UnsafeFieldName(%v)\n", g.skipMemberNameUnescaping)
516 fmt.Fprintln(g.out, " in.WantColon()")
517 fmt.Fprintln(g.out, " if in.IsNull() {")
518 fmt.Fprintln(g.out, " in.Skip()")
519 fmt.Fprintln(g.out, " in.WantComma()")
520 fmt.Fprintln(g.out, " continue")
521 fmt.Fprintln(g.out, " }")
522
523 fmt.Fprintln(g.out, " switch key {")
524 for _, f := range fs {
525 if err := g.genStructFieldDecoder(t, f); err != nil {
526 return err
527 }
528 }
529
530 fmt.Fprintln(g.out, " default:")
531 if g.disallowUnknownFields {
532 fmt.Fprintln(g.out, ` in.AddError(&jlexer.LexerError{
533 Offset: in.GetPos(),
534 Reason: "unknown field",
535 Data: key,
536 })`)
537 } else if hasUnknownsUnmarshaler(t) {
538 fmt.Fprintln(g.out, " out.UnmarshalUnknown(in, key)")
539 } else {
540 fmt.Fprintln(g.out, " in.SkipRecursive()")
541 }
542 fmt.Fprintln(g.out, " }")
543 fmt.Fprintln(g.out, " in.WantComma()")
544 fmt.Fprintln(g.out, " }")
545 fmt.Fprintln(g.out, " in.Delim('}')")
546 fmt.Fprintln(g.out, " if isTopLevel {")
547 fmt.Fprintln(g.out, " in.Consumed()")
548 fmt.Fprintln(g.out, " }")
549
550 for _, f := range fs {
551 g.genRequiredFieldCheck(t, f)
552 }
553
554 fmt.Fprintln(g.out, "}")
555
556 return nil
557 }
558
559 func (g *Generator) genStructUnmarshaler(t reflect.Type) error {
560 switch t.Kind() {
561 case reflect.Slice, reflect.Array, reflect.Map, reflect.Struct:
562 default:
563 return fmt.Errorf("cannot generate encoder/decoder for %v, not a struct/slice/array/map type", t)
564 }
565
566 fname := g.getDecoderName(t)
567 typ := g.getType(t)
568
569 if !g.noStdMarshalers {
570 fmt.Fprintln(g.out, "// UnmarshalJSON supports json.Unmarshaler interface")
571 fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalJSON(data []byte) error {")
572 fmt.Fprintln(g.out, " r := jlexer.Lexer{Data: data}")
573 fmt.Fprintln(g.out, " "+fname+"(&r, v)")
574 fmt.Fprintln(g.out, " return r.Error()")
575 fmt.Fprintln(g.out, "}")
576 }
577
578 fmt.Fprintln(g.out, "// UnmarshalEasyJSON supports easyjson.Unmarshaler interface")
579 fmt.Fprintln(g.out, "func (v *"+typ+") UnmarshalEasyJSON(l *jlexer.Lexer) {")
580 fmt.Fprintln(g.out, " "+fname+"(l, v)")
581 fmt.Fprintln(g.out, "}")
582
583 return nil
584 }
585
View as plain text