1package jsoncolor
2
3import (
4 "bytes"
5 "encoding"
6 "encoding/base64"
7 "math"
8 "reflect"
9 "sort"
10 "strconv"
11 "sync"
12 "time"
13 "unicode/utf8"
14 "unsafe"
15)
16
17const hex = "0123456789abcdef"
18
19func (e encoder) encodeNull(b []byte, p unsafe.Pointer) ([]byte, error) {
20 return e.clrs.appendNull(b), nil
21}
22
23func (e encoder) encodeBool(b []byte, p unsafe.Pointer) ([]byte, error) {
24 return e.clrs.appendBool(b, *(*bool)(p)), nil
25}
26
27func (e encoder) encodeInt(b []byte, p unsafe.Pointer) ([]byte, error) {
28 return e.clrs.appendInt64(b, int64(*(*int)(p))), nil
29}
30
31func (e encoder) encodeInt8(b []byte, p unsafe.Pointer) ([]byte, error) {
32 return e.clrs.appendInt64(b, int64(*(*int8)(p))), nil
33}
34
35func (e encoder) encodeInt16(b []byte, p unsafe.Pointer) ([]byte, error) {
36 return e.clrs.appendInt64(b, int64(*(*int16)(p))), nil
37}
38
39func (e encoder) encodeInt32(b []byte, p unsafe.Pointer) ([]byte, error) {
40 return e.clrs.appendInt64(b, int64(*(*int32)(p))), nil
41}
42
43func (e encoder) encodeInt64(b []byte, p unsafe.Pointer) ([]byte, error) {
44 return e.clrs.appendInt64(b, *(*int64)(p)), nil
45}
46
47func (e encoder) encodeUint(b []byte, p unsafe.Pointer) ([]byte, error) {
48 return e.clrs.appendUint64(b, uint64(*(*uint)(p))), nil
49}
50
51func (e encoder) encodeUintptr(b []byte, p unsafe.Pointer) ([]byte, error) {
52 return e.clrs.appendUint64(b, uint64(*(*uintptr)(p))), nil
53}
54
55func (e encoder) encodeUint8(b []byte, p unsafe.Pointer) ([]byte, error) {
56 return e.clrs.appendUint64(b, uint64(*(*uint8)(p))), nil
57}
58
59func (e encoder) encodeUint16(b []byte, p unsafe.Pointer) ([]byte, error) {
60 return e.clrs.appendUint64(b, uint64(*(*uint16)(p))), nil
61}
62
63func (e encoder) encodeUint32(b []byte, p unsafe.Pointer) ([]byte, error) {
64 return e.clrs.appendUint64(b, uint64(*(*uint32)(p))), nil
65}
66
67func (e encoder) encodeUint64(b []byte, p unsafe.Pointer) ([]byte, error) {
68 return e.clrs.appendUint64(b, *(*uint64)(p)), nil
69}
70
71func (e encoder) encodeFloat32(b []byte, p unsafe.Pointer) ([]byte, error) {
72 if e.clrs == nil {
73 return e.encodeFloat(b, float64(*(*float32)(p)), 32)
74 }
75
76 b = append(b, e.clrs.Number...)
77 var err error
78 b, err = e.encodeFloat(b, float64(*(*float32)(p)), 32)
79 b = append(b, ansiReset...)
80 return b, err
81}
82
83func (e encoder) encodeFloat64(b []byte, p unsafe.Pointer) ([]byte, error) {
84 if e.clrs == nil {
85 return e.encodeFloat(b, *(*float64)(p), 64)
86 }
87
88 b = append(b, e.clrs.Number...)
89 var err error
90 b, err = e.encodeFloat(b, *(*float64)(p), 64)
91 b = append(b, ansiReset...)
92 return b, err
93}
94
95func (e encoder) encodeFloat(b []byte, f float64, bits int) ([]byte, error) {
96 switch {
97 case math.IsNaN(f):
98 return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "NaN"}
99 case math.IsInf(f, 0):
100 return b, &UnsupportedValueError{Value: reflect.ValueOf(f), Str: "inf"}
101 }
102
103 // Convert as if by ES6 number to string conversion.
104 // This matches most other JSON generators.
105 // See golang.org/issue/6384 and golang.org/issue/14135.
106 // Like fmt %g, but the exponent cutoffs are different
107 // and exponents themselves are not padded to two digits.
108 abs := math.Abs(f)
109 fmt := byte('f')
110 // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
111 if abs != 0 {
112 if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
113 fmt = 'e'
114 }
115 }
116
117 b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
118
119 if fmt == 'e' {
120 // clean up e-09 to e-9
121 n := len(b)
122 if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
123 b[n-2] = b[n-1]
124 b = b[:n-1]
125 }
126 }
127
128 return b, nil
129}
130
131func (e encoder) encodeNumber(b []byte, p unsafe.Pointer) ([]byte, error) {
132 n := *(*Number)(p)
133 if n == "" {
134 n = "0"
135 }
136
137 _, _, err := parseNumber(stringToBytes(string(n)))
138 if err != nil {
139 return b, err
140 }
141
142 if e.clrs == nil {
143 return append(b, n...), nil
144 }
145
146 b = append(b, e.clrs.Number...)
147 b = append(b, n...)
148 b = append(b, ansiReset...)
149 return b, nil
150}
151
152func (e encoder) encodeKey(b []byte, p unsafe.Pointer) ([]byte, error) {
153 if e.clrs == nil {
154 return e.doEncodeString(b, p)
155 }
156
157 b = append(b, e.clrs.Key...)
158 var err error
159 b, err = e.doEncodeString(b, p)
160 b = append(b, ansiReset...)
161 return b, err
162}
163
164func (e encoder) encodeString(b []byte, p unsafe.Pointer) ([]byte, error) {
165 if e.clrs == nil {
166 return e.doEncodeString(b, p)
167 }
168
169 b = append(b, e.clrs.String...)
170 var err error
171 b, err = e.doEncodeString(b, p)
172 b = append(b, ansiReset...)
173 return b, err
174}
175
176func (e encoder) doEncodeString(b []byte, p unsafe.Pointer) ([]byte, error) {
177 s := *(*string)(p)
178 i := 0
179 j := 0
180 escapeHTML := (e.flags & EscapeHTML) != 0
181
182 b = append(b, '"')
183
184 for j < len(s) {
185 c := s[j]
186
187 if c >= 0x20 && c <= 0x7f && c != '\\' && c != '"' && (!escapeHTML || (c != '<' && c != '>' && c != '&')) {
188 // fast path: most of the time, printable ascii characters are used
189 j++
190 continue
191 }
192
193 switch c {
194 case '\\', '"':
195 b = append(b, s[i:j]...)
196 b = append(b, '\\', c)
197 i = j + 1
198 j = j + 1
199 continue
200
201 case '\n':
202 b = append(b, s[i:j]...)
203 b = append(b, '\\', 'n')
204 i = j + 1
205 j = j + 1
206 continue
207
208 case '\r':
209 b = append(b, s[i:j]...)
210 b = append(b, '\\', 'r')
211 i = j + 1
212 j = j + 1
213 continue
214
215 case '\t':
216 b = append(b, s[i:j]...)
217 b = append(b, '\\', 't')
218 i = j + 1
219 j = j + 1
220 continue
221
222 case '<', '>', '&':
223 b = append(b, s[i:j]...)
224 b = append(b, `\u00`...)
225 b = append(b, hex[c>>4], hex[c&0xF])
226 i = j + 1
227 j = j + 1
228 continue
229 }
230
231 // This encodes bytes < 0x20 except for \t, \n and \r.
232 if c < 0x20 {
233 b = append(b, s[i:j]...)
234 b = append(b, `\u00`...)
235 b = append(b, hex[c>>4], hex[c&0xF])
236 i = j + 1
237 j = j + 1
238 continue
239 }
240
241 r, size := utf8.DecodeRuneInString(s[j:])
242
243 if r == utf8.RuneError && size == 1 {
244 b = append(b, s[i:j]...)
245 b = append(b, `\ufffd`...)
246 i = j + size
247 j = j + size
248 continue
249 }
250
251 switch r {
252 case '\u2028', '\u2029':
253 // U+2028 is LINE SEPARATOR.
254 // U+2029 is PARAGRAPH SEPARATOR.
255 // They are both technically valid characters in JSON strings,
256 // but don't work in JSONP, which has to be evaluated as JavaScript,
257 // and can lead to security holes there. It is valid JSON to
258 // escape them, so we do so unconditionally.
259 // See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
260 b = append(b, s[i:j]...)
261 b = append(b, `\u202`...)
262 b = append(b, hex[r&0xF])
263 i = j + size
264 j = j + size
265 continue
266 }
267
268 j += size
269 }
270
271 b = append(b, s[i:]...)
272 b = append(b, '"')
273 return b, nil
274}
275
276func (e encoder) encodeToString(b []byte, p unsafe.Pointer, encode encodeFunc) ([]byte, error) {
277 i := len(b)
278
279 b, err := encode(e, b, p)
280 if err != nil {
281 return b, err
282 }
283
284 j := len(b)
285 s := b[i:]
286
287 if b, err = e.doEncodeString(b, unsafe.Pointer(&s)); err != nil {
288 return b, err
289 }
290
291 n := copy(b[i:], b[j:])
292 return b[:i+n], nil
293}
294
295func (e encoder) encodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) {
296 if e.clrs == nil {
297 return e.doEncodeBytes(b, p)
298 }
299
300 b = append(b, e.clrs.Bytes...)
301 var err error
302 b, err = e.doEncodeBytes(b, p)
303 return append(b, ansiReset...), err
304}
305
306func (e encoder) doEncodeBytes(b []byte, p unsafe.Pointer) ([]byte, error) {
307 v := *(*[]byte)(p)
308 if v == nil {
309 return e.clrs.appendNull(b), nil
310 }
311
312 n := base64.StdEncoding.EncodedLen(len(v)) + 2
313
314 if avail := cap(b) - len(b); avail < n {
315 newB := make([]byte, cap(b)+(n-avail))
316 copy(newB, b)
317 b = newB[:len(b)]
318 }
319
320 i := len(b)
321 j := len(b) + n
322
323 b = b[:j]
324 b[i] = '"'
325 base64.StdEncoding.Encode(b[i+1:j-1], v)
326 b[j-1] = '"'
327 return b, nil
328}
329
330func (e encoder) encodeDuration(b []byte, p unsafe.Pointer) ([]byte, error) {
331 // NOTE: The segmentj encoder does special handling for time.Duration (converts to string).
332 // The stdlib encoder does not. It just outputs the int64 value.
333 // We choose to follow the stdlib pattern, for fuller compatibility.
334
335 b = e.clrs.appendInt64(b, int64(*(*time.Duration)(p)))
336 return b, nil
337
338 // NOTE: if we were to follow the segmentj pattern, we'd execute the code below.
339 //if e.clrs == nil {
340 // b = append(b, '"')
341 //
342 // b = appendDuration(b, *(*time.Duration)(p))
343 // b = append(b, '"')
344 // return b, nil
345 //}
346 //
347 //b = append(b, e.clrs.Time...)
348 //b = append(b, '"')
349 //b = appendDuration(b, *(*time.Duration)(p))
350 //b = append(b, '"')
351 //b = append(b, ansiReset...)
352 //return b, nil
353}
354
355func (e encoder) encodeTime(b []byte, p unsafe.Pointer) ([]byte, error) {
356 if e.clrs == nil {
357 t := *(*time.Time)(p)
358 b = append(b, '"')
359 b = t.AppendFormat(b, time.RFC3339Nano)
360 b = append(b, '"')
361 return b, nil
362 }
363
364 t := *(*time.Time)(p)
365 b = append(b, e.clrs.Time...)
366 b = append(b, '"')
367 b = t.AppendFormat(b, time.RFC3339Nano)
368 b = append(b, '"')
369 b = append(b, ansiReset...)
370 return b, nil
371}
372
373func (e encoder) encodeArray(b []byte, p unsafe.Pointer, n int, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) {
374 var start = len(b)
375 var err error
376
377 b = e.clrs.appendPunc(b, '[')
378
379 if n > 0 {
380 e.indentr.push()
381 for i := 0; i < n; i++ {
382 if i != 0 {
383 b = e.clrs.appendPunc(b, ',')
384 }
385
386 b = e.indentr.appendByte(b, '\n')
387 b = e.indentr.appendIndent(b)
388
389 if b, err = encode(e, b, unsafe.Pointer(uintptr(p)+(uintptr(i)*size))); err != nil {
390 return b[:start], err
391 }
392 }
393 e.indentr.pop()
394 b = e.indentr.appendByte(b, '\n')
395 b = e.indentr.appendIndent(b)
396 }
397
398 b = e.clrs.appendPunc(b, ']')
399
400 return b, nil
401}
402
403func (e encoder) encodeSlice(b []byte, p unsafe.Pointer, size uintptr, t reflect.Type, encode encodeFunc) ([]byte, error) {
404 s := (*slice)(p)
405
406 if s.data == nil && s.len == 0 && s.cap == 0 {
407 return e.clrs.appendNull(b), nil
408 }
409
410 return e.encodeArray(b, s.data, s.len, size, t, encode)
411}
412
413func (e encoder) encodeMap(b []byte, p unsafe.Pointer, t reflect.Type, encodeKey, encodeValue encodeFunc, sortKeys sortFunc) ([]byte, error) {
414 m := reflect.NewAt(t, p).Elem()
415 if m.IsNil() {
416 return e.clrs.appendNull(b), nil
417 }
418
419 keys := m.MapKeys()
420 if sortKeys != nil && (e.flags&SortMapKeys) != 0 {
421 sortKeys(keys)
422 }
423
424 var start = len(b)
425 var err error
426 b = e.clrs.appendPunc(b, '{')
427
428 if len(keys) != 0 {
429 b = e.indentr.appendByte(b, '\n')
430
431 e.indentr.push()
432 for i, k := range keys {
433 v := m.MapIndex(k)
434
435 if i != 0 {
436 b = e.clrs.appendPunc(b, ',')
437 b = e.indentr.appendByte(b, '\n')
438 }
439
440 b = e.indentr.appendIndent(b)
441 if b, err = encodeKey(e, b, (*iface)(unsafe.Pointer(&k)).ptr); err != nil {
442 return b[:start], err
443 }
444
445 b = e.clrs.appendPunc(b, ':')
446 b = e.indentr.appendByte(b, ' ')
447
448 if b, err = encodeValue(e, b, (*iface)(unsafe.Pointer(&v)).ptr); err != nil {
449 return b[:start], err
450 }
451 }
452 b = e.indentr.appendByte(b, '\n')
453 e.indentr.pop()
454 b = e.indentr.appendIndent(b)
455 }
456
457 b = e.clrs.appendPunc(b, '}')
458 return b, nil
459}
460
461type element struct {
462 key string
463 val interface{}
464 raw RawMessage
465}
466
467type mapslice struct {
468 elements []element
469}
470
471func (m *mapslice) Len() int { return len(m.elements) }
472func (m *mapslice) Less(i, j int) bool { return m.elements[i].key < m.elements[j].key }
473func (m *mapslice) Swap(i, j int) { m.elements[i], m.elements[j] = m.elements[j], m.elements[i] }
474
475var mapslicePool = sync.Pool{
476 New: func() interface{} { return new(mapslice) },
477}
478
479func (e encoder) encodeMapStringInterface(b []byte, p unsafe.Pointer) ([]byte, error) {
480 m := *(*map[string]interface{})(p)
481 if m == nil {
482 return e.clrs.appendNull(b), nil
483 }
484
485 if (e.flags & SortMapKeys) == 0 {
486 // Optimized code path when the program does not need the map keys to be
487 // sorted.
488 b = e.clrs.appendPunc(b, '{')
489
490 if len(m) != 0 {
491 b = e.indentr.appendByte(b, '\n')
492
493 var err error
494 var i = 0
495
496 e.indentr.push()
497 for k, v := range m {
498 if i != 0 {
499 b = e.clrs.appendPunc(b, ',')
500 b = e.indentr.appendByte(b, '\n')
501 }
502
503 b = e.indentr.appendIndent(b)
504
505 b, err = e.encodeKey(b, unsafe.Pointer(&k))
506 if err != nil {
507 return b, err
508 }
509
510 b = e.clrs.appendPunc(b, ':')
511 b = e.indentr.appendByte(b, ' ')
512
513 b, err = Append(b, v, e.flags, e.clrs, e.indentr)
514 if err != nil {
515 return b, err
516 }
517
518 i++
519 }
520 b = e.indentr.appendByte(b, '\n')
521 e.indentr.pop()
522 b = e.indentr.appendIndent(b)
523 }
524
525 b = e.clrs.appendPunc(b, '}')
526 return b, nil
527 }
528
529 s := mapslicePool.Get().(*mapslice)
530 if cap(s.elements) < len(m) {
531 s.elements = make([]element, 0, align(10, uintptr(len(m))))
532 }
533 for key, val := range m {
534 s.elements = append(s.elements, element{key: key, val: val})
535 }
536 sort.Sort(s)
537
538 var start = len(b)
539 var err error
540 b = e.clrs.appendPunc(b, '{')
541
542 if len(s.elements) > 0 {
543 b = e.indentr.appendByte(b, '\n')
544
545 e.indentr.push()
546 for i, elem := range s.elements {
547 if i != 0 {
548 b = e.clrs.appendPunc(b, ',')
549 b = e.indentr.appendByte(b, '\n')
550 }
551
552 b = e.indentr.appendIndent(b)
553
554 b, _ = e.encodeKey(b, unsafe.Pointer(&elem.key))
555 b = e.clrs.appendPunc(b, ':')
556 b = e.indentr.appendByte(b, ' ')
557
558 b, err = Append(b, elem.val, e.flags, e.clrs, e.indentr)
559 if err != nil {
560 break
561 }
562 }
563 b = e.indentr.appendByte(b, '\n')
564 e.indentr.pop()
565 b = e.indentr.appendIndent(b)
566 }
567
568 for i := range s.elements {
569 s.elements[i] = element{}
570 }
571
572 s.elements = s.elements[:0]
573 mapslicePool.Put(s)
574
575 if err != nil {
576 return b[:start], err
577 }
578
579 b = e.clrs.appendPunc(b, '}')
580 return b, nil
581}
582
583func (e encoder) encodeMapStringRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) {
584 m := *(*map[string]RawMessage)(p)
585 if m == nil {
586 return e.clrs.appendNull(b), nil
587 }
588
589 if (e.flags & SortMapKeys) == 0 {
590 // Optimized code path when the program does not need the map keys to be
591 // sorted.
592 b = e.clrs.appendPunc(b, '{')
593
594 if len(m) != 0 {
595 b = e.indentr.appendByte(b, '\n')
596
597 var err error
598 var i = 0
599
600 e.indentr.push()
601 for k, v := range m {
602 if i != 0 {
603 b = e.clrs.appendPunc(b, ',')
604 b = e.indentr.appendByte(b, '\n')
605 }
606
607 b = e.indentr.appendIndent(b)
608
609 b, _ = e.encodeKey(b, unsafe.Pointer(&k))
610
611 b = e.clrs.appendPunc(b, ':')
612 b = e.indentr.appendByte(b, ' ')
613
614 b, err = e.encodeRawMessage(b, unsafe.Pointer(&v))
615 if err != nil {
616 break
617 }
618
619 i++
620 }
621 b = e.indentr.appendByte(b, '\n')
622 e.indentr.pop()
623 b = e.indentr.appendIndent(b)
624 }
625
626 b = e.clrs.appendPunc(b, '}')
627 return b, nil
628 }
629
630 s := mapslicePool.Get().(*mapslice)
631 if cap(s.elements) < len(m) {
632 s.elements = make([]element, 0, align(10, uintptr(len(m))))
633 }
634 for key, raw := range m {
635 s.elements = append(s.elements, element{key: key, raw: raw})
636 }
637 sort.Sort(s)
638
639 var start = len(b)
640 var err error
641 b = e.clrs.appendPunc(b, '{')
642
643 if len(s.elements) > 0 {
644 b = e.indentr.appendByte(b, '\n')
645
646 e.indentr.push()
647
648 for i, elem := range s.elements {
649 if i != 0 {
650 b = e.clrs.appendPunc(b, ',')
651 b = e.indentr.appendByte(b, '\n')
652 }
653
654 b = e.indentr.appendIndent(b)
655
656 b, _ = e.encodeKey(b, unsafe.Pointer(&elem.key))
657 b = e.clrs.appendPunc(b, ':')
658 b = e.indentr.appendByte(b, ' ')
659
660 b, err = e.encodeRawMessage(b, unsafe.Pointer(&elem.raw))
661 if err != nil {
662 break
663 }
664 }
665 b = e.indentr.appendByte(b, '\n')
666 e.indentr.pop()
667 b = e.indentr.appendIndent(b)
668 }
669
670 for i := range s.elements {
671 s.elements[i] = element{}
672 }
673
674 s.elements = s.elements[:0]
675 mapslicePool.Put(s)
676
677 if err != nil {
678 return b[:start], err
679 }
680
681 b = e.clrs.appendPunc(b, '}')
682 return b, nil
683}
684
685func (e encoder) encodeStruct(b []byte, p unsafe.Pointer, st *structType) ([]byte, error) {
686 var start = len(b)
687 var err error
688 var k string
689 var n int
690
691 b = e.clrs.appendPunc(b, '{')
692
693 if len(st.fields) > 0 {
694 b = e.indentr.appendByte(b, '\n')
695 }
696
697 e.indentr.push()
698
699 for i := range st.fields {
700 f := &st.fields[i]
701 v := unsafe.Pointer(uintptr(p) + f.offset)
702
703 if f.omitempty && f.empty(v) {
704 continue
705 }
706
707 if n != 0 {
708 b = e.clrs.appendPunc(b, ',')
709 b = e.indentr.appendByte(b, '\n')
710 }
711
712 if (e.flags & EscapeHTML) != 0 {
713 k = f.html
714 } else {
715 k = f.json
716 }
717
718 lengthBeforeKey := len(b)
719 b = e.indentr.appendIndent(b)
720
721 if e.clrs == nil {
722 b = append(b, k...)
723 } else {
724 b = append(b, e.clrs.Key...)
725 b = append(b, k...)
726 b = append(b, ansiReset...)
727 }
728
729 b = e.clrs.appendPunc(b, ':')
730
731 b = e.indentr.appendByte(b, ' ')
732
733 if b, err = f.codec.encode(e, b, v); err != nil {
734 if err == (rollback{}) {
735 b = b[:lengthBeforeKey]
736 continue
737 }
738 return b[:start], err
739 }
740
741 n++
742 }
743
744 if n > 0 {
745 b = e.indentr.appendByte(b, '\n')
746 }
747
748 e.indentr.pop()
749 b = e.indentr.appendIndent(b)
750
751 b = e.clrs.appendPunc(b, '}')
752 return b, nil
753}
754
755type rollback struct{}
756
757func (rollback) Error() string { return "rollback" }
758
759func (e encoder) encodeEmbeddedStructPointer(b []byte, p unsafe.Pointer, t reflect.Type, unexported bool, offset uintptr, encode encodeFunc) ([]byte, error) {
760 p = *(*unsafe.Pointer)(p)
761 if p == nil {
762 return b, rollback{}
763 }
764 return encode(e, b, unsafe.Pointer(uintptr(p)+offset))
765}
766
767func (e encoder) encodePointer(b []byte, p unsafe.Pointer, t reflect.Type, encode encodeFunc) ([]byte, error) {
768 if p = *(*unsafe.Pointer)(p); p != nil {
769 return encode(e, b, p)
770 }
771 return e.encodeNull(b, nil)
772}
773
774func (e encoder) encodeInterface(b []byte, p unsafe.Pointer) ([]byte, error) {
775 return Append(b, *(*interface{})(p), e.flags, e.clrs, e.indentr)
776}
777
778func (e encoder) encodeMaybeEmptyInterface(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) {
779 return Append(b, reflect.NewAt(t, p).Elem().Interface(), e.flags, e.clrs, e.indentr)
780}
781
782func (e encoder) encodeUnsupportedTypeError(b []byte, p unsafe.Pointer, t reflect.Type) ([]byte, error) {
783 return b, &UnsupportedTypeError{Type: t}
784}
785
786// encodeRawMessage encodes a RawMessage to bytes. Unfortunately, this
787// implementation has a deficiency: it uses Unmarshal to build an
788// object from the RawMessage, which in the case of a struct, results
789// in a map being constructed, and thus the order of the keys is not
790// guaranteed to be maintained. A superior implementation would decode and
791// then re-encode (with color/indentation) the basic JSON tokens on the fly.
792// Note also that if TrustRawMessage is set, and the RawMessage is
793// invalid JSON (cannot be parsed by Unmarshal), then this function
794// falls back to encodeRawMessageNoParseTrusted, which seems to exhibit the
795// correct behavior. It's a bit of a mess, but seems to do the trick.
796func (e encoder) encodeRawMessage(b []byte, p unsafe.Pointer) ([]byte, error) {
797 v := *(*RawMessage)(p)
798
799 if v == nil {
800 return e.clrs.appendNull(b), nil
801 }
802
803 var s []byte
804
805 if (e.flags & TrustRawMessage) != 0 {
806 s = v
807 } else {
808 var err error
809 s, _, err = parseValue(v)
810 if err != nil {
811 return b, &UnsupportedValueError{Value: reflect.ValueOf(v), Str: err.Error()}
812 }
813 }
814
815 var x interface{}
816 if err := Unmarshal(s, &x); err != nil {
817 return e.encodeRawMessageNoParseTrusted(b, p)
818 }
819
820 return Append(b, x, e.flags, e.clrs, e.indentr)
821}
822
823// encodeRawMessageNoParseTrusted is a fallback method that is
824// used by encodeRawMessage if it fails to parse a trusted RawMessage.
825// The (invalid) JSON produced by this method is not colorized.
826// This method may have wonky logic or even bugs in it; little effort
827// has been expended on it because it's a rarely visited edge case.
828func (e encoder) encodeRawMessageNoParseTrusted(b []byte, p unsafe.Pointer) ([]byte, error) {
829 v := *(*RawMessage)(p)
830
831 if v == nil {
832 return e.clrs.appendNull(b), nil
833 }
834
835 var s []byte
836
837 if (e.flags & TrustRawMessage) != 0 {
838 s = v
839 } else {
840 var err error
841 s, _, err = parseValue(v)
842 if err != nil {
843 return b, &UnsupportedValueError{Value: reflect.ValueOf(v), Str: err.Error()}
844 }
845 }
846
847 if e.indentr == nil {
848 if (e.flags & EscapeHTML) != 0 {
849 return appendCompactEscapeHTML(b, s), nil
850 }
851
852 return append(b, s...), nil
853 }
854
855 // In order to get the tests inherited from the original segmentio
856 // encoder to work, we need to support indentation.
857
858 // This below is sloppy, but seems to work.
859 if (e.flags & EscapeHTML) != 0 {
860 s = appendCompactEscapeHTML(nil, s)
861 }
862
863 // The "prefix" arg to Indent is the current indentation.
864 pre := e.indentr.appendIndent(nil)
865
866 buf := &bytes.Buffer{}
867 // And now we just make use of the existing Indent function.
868 err := Indent(buf, s, string(pre), e.indentr.indent)
869 if err != nil {
870 return b, err
871 }
872
873 s = buf.Bytes()
874
875 return append(b, s...), nil
876}
877
878
879// encodeJSONMarshaler suffers from the same defect as encodeRawMessage; it
880// can result in keys being reordered.
881func (e encoder) encodeJSONMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) {
882 v := reflect.NewAt(t, p)
883
884 if !pointer {
885 v = v.Elem()
886 }
887
888 switch v.Kind() {
889 case reflect.Ptr, reflect.Interface:
890 if v.IsNil() {
891 return e.clrs.appendNull(b), nil
892 }
893 }
894
895 j, err := v.Interface().(Marshaler).MarshalJSON()
896 if err != nil {
897 return b, err
898 }
899
900 // We effectively delegate to the encodeRawMessage method.
901 return Append(b, RawMessage(j), e.flags, e.clrs, e.indentr)
902}
903
904func (e encoder) encodeTextMarshaler(b []byte, p unsafe.Pointer, t reflect.Type, pointer bool) ([]byte, error) {
905 v := reflect.NewAt(t, p)
906
907 if !pointer {
908 v = v.Elem()
909 }
910
911 switch v.Kind() {
912 case reflect.Ptr, reflect.Interface:
913 if v.IsNil() {
914 return e.clrs.appendNull(b), nil
915 }
916 }
917
918 s, err := v.Interface().(encoding.TextMarshaler).MarshalText()
919 if err != nil {
920 return b, err
921 }
922
923 if e.clrs == nil {
924 return e.doEncodeString(b, unsafe.Pointer(&s))
925 }
926
927 b = append(b, e.clrs.TextMarshaler...)
928 b, err = e.doEncodeString(b, unsafe.Pointer(&s))
929 b = append(b, ansiReset...)
930 return b, err
931}
932
933func appendCompactEscapeHTML(dst []byte, src []byte) []byte {
934 start := 0
935 escape := false
936 inString := false
937
938 for i, c := range src {
939 if !inString {
940 switch c {
941 case '"': // enter string
942 inString = true
943 case ' ', '\n', '\r', '\t': // skip space
944 if start < i {
945 dst = append(dst, src[start:i]...)
946 }
947 start = i + 1
948 }
949 continue
950 }
951
952 if escape {
953 escape = false
954 continue
955 }
956
957 if c == '\\' {
958 escape = true
959 continue
960 }
961
962 if c == '"' {
963 inString = false
964 continue
965 }
966
967 if c == '<' || c == '>' || c == '&' {
968 if start < i {
969 dst = append(dst, src[start:i]...)
970 }
971 dst = append(dst, `\u00`...)
972 dst = append(dst, hex[c>>4], hex[c&0xF])
973 start = i + 1
974 continue
975 }
976
977 // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
978 if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
979 if start < i {
980 dst = append(dst, src[start:i]...)
981 }
982 dst = append(dst, `\u202`...)
983 dst = append(dst, hex[src[i+2]&0xF])
984 start = i + 3
985 continue
986 }
987 }
988
989 if start < len(src) {
990 dst = append(dst, src[start:]...)
991 }
992
993 return dst
994}
995
996// indenter is used to indent JSON. The push and pop methods
997// change indentation level. The appendIndent method appends the
998// computed indentation. The appendByte method appends a byte. All
999// methods are safe to use with a nil receiver.
1000type indenter struct {
1001 disabled bool
1002 prefix string
1003 indent string
1004 depth int
1005}
1006
1007// newIndenter returns a new indenter instance. If prefix and
1008// indent are both empty, the indenter is effectively disabled,
1009// and the appendIndent and appendByte methods are no-op.
1010func newIndenter(prefix, indent string) *indenter {
1011 return &indenter{
1012 disabled: prefix == "" && indent == "",
1013 prefix: prefix,
1014 indent: indent,
1015 }
1016}
1017
1018// push increases the indentation level.
1019func (in *indenter) push() {
1020 if in != nil {
1021 in.depth++
1022 }
1023}
1024
1025// pop decreases the indentation level.
1026func (in *indenter) pop() {
1027 if in != nil {
1028 in.depth--
1029 }
1030}
1031
1032// appendByte appends a to b if the indenter is non-nil and enabled.
1033// Otherwise b is returned unmodified.
1034func (in *indenter) appendByte(b []byte, a byte) []byte {
1035 if in == nil || in.disabled {
1036 return b
1037 }
1038
1039 return append(b, a)
1040}
1041
1042// appendIndent writes indentation to b, returning the resulting slice.
1043// If the indenter is nil or disabled b is returned unchanged.
1044func (in *indenter) appendIndent(b []byte) []byte {
1045 if in == nil || in.disabled {
1046 return b
1047 }
1048
1049 b = append(b, in.prefix...)
1050 for i := 0; i < in.depth; i++ {
1051 b = append(b, in.indent...)
1052 }
1053 return b
1054}