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