github.com/searKing/golang/go@v1.2.117/encoding/prettyjson/encode.go (about)

     1  // Copyright 2023 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package prettyjson
     6  
     7  import (
     8  	"bytes"
     9  	"encoding"
    10  	"encoding/base64"
    11  	"encoding/json"
    12  	"fmt"
    13  	"math"
    14  	"net/url"
    15  	"reflect"
    16  	"sort"
    17  	"strconv"
    18  	"strings"
    19  	"sync"
    20  	"unicode"
    21  	"unicode/utf8"
    22  
    23  	bytes_ "github.com/searKing/golang/go/bytes"
    24  	strings_ "github.com/searKing/golang/go/strings"
    25  )
    26  
    27  // Marshal returns the JSON encoding of v, and support truncate.
    28  func Marshal(v any, opts ...EncOptsOption) ([]byte, error) {
    29  	e := newEncodeState()
    30  	defer encodeStatePool.Put(e)
    31  
    32  	var opt encOpts
    33  	opt.escapeHTML = true
    34  	opt.ApplyOptions(opts...)
    35  	err := e.marshal(v, opt)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	buf := append([]byte(nil), e.Bytes()...)
    40  	return buf, nil
    41  }
    42  
    43  // MarshalIndent is like Marshal but applies Indent to format the output.
    44  // Each JSON element in the output will begin on a new line beginning with prefix
    45  // followed by one or more copies of indent according to the indentation nesting.
    46  func MarshalIndent(v any, prefix, indent string, opts ...EncOptsOption) ([]byte, error) {
    47  	b, err := Marshal(v, opts...)
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	var buf bytes.Buffer
    52  	err = json.Indent(&buf, b, prefix, indent)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	return buf.Bytes(), nil
    57  }
    58  
    59  // Marshaler is the interface implemented by types that
    60  // can marshal themselves into valid JSON.
    61  type Marshaler = json.Marshaler
    62  
    63  // An UnsupportedTypeError is returned by Marshal when attempting
    64  // to encode an unsupported value type.
    65  type UnsupportedTypeError = json.UnsupportedTypeError
    66  
    67  // An UnsupportedValueError is returned by Marshal when attempting
    68  // to encode an unsupported value.
    69  type UnsupportedValueError = json.UnsupportedValueError
    70  
    71  // A MarshalerError represents an error from calling a MarshalJSON or MarshalText method.
    72  type MarshalerError = json.MarshalerError
    73  
    74  var hex = "0123456789abcdef"
    75  
    76  // An encodeState encodes JSON into a bytes.Buffer.
    77  type encodeState struct {
    78  	bytes.Buffer // accumulated output
    79  
    80  	// Keep track of what pointers we've seen in the current recursive call
    81  	// path, to avoid cycles that could lead to a stack overflow. Only do
    82  	// the relatively expensive map operations if ptrLevel is larger than
    83  	// startDetectingCyclesAfter, so that we skip the work if we're within a
    84  	// reasonable amount of nested pointers deep.
    85  	ptrLevel uint
    86  	ptrSeen  map[any]struct{}
    87  }
    88  
    89  const startDetectingCyclesAfter = 1000
    90  
    91  var encodeStatePool sync.Pool
    92  
    93  func newEncodeState() *encodeState {
    94  	if v := encodeStatePool.Get(); v != nil {
    95  		e := v.(*encodeState)
    96  		e.Reset()
    97  		if len(e.ptrSeen) > 0 {
    98  			panic("ptrEncoder.encode should have emptied ptrSeen via defers")
    99  		}
   100  		e.ptrLevel = 0
   101  		return e
   102  	}
   103  	return &encodeState{ptrSeen: make(map[any]struct{})}
   104  }
   105  
   106  // jsonError is an error wrapper type for internal use only.
   107  // Panics with errors are wrapped in jsonError so that the top-level recover
   108  // can distinguish intentional panics from this package.
   109  type jsonError struct{ error }
   110  
   111  func (e *encodeState) marshal(v any, opts encOpts) (err error) {
   112  	defer func() {
   113  		if r := recover(); r != nil {
   114  			if je, ok := r.(jsonError); ok {
   115  				err = je.error
   116  			} else {
   117  				panic(r)
   118  			}
   119  		}
   120  	}()
   121  	e.reflectValue(reflect.ValueOf(v), opts)
   122  	return nil
   123  }
   124  
   125  // error aborts the encoding by panicking with err wrapped in jsonError.
   126  func (e *encodeState) error(err error) {
   127  	panic(jsonError{err})
   128  }
   129  
   130  func isEmptyValue(v reflect.Value) bool {
   131  	// @diff
   132  	defer func() {
   133  		if r := recover(); r != nil {
   134  			return
   135  		}
   136  	}()
   137  	switch v.Kind() {
   138  	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
   139  		return v.Len() == 0
   140  	case reflect.Bool:
   141  		return v.Bool() == false
   142  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   143  		return v.Int() == 0
   144  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   145  		return v.Uint() == 0
   146  	case reflect.Float32, reflect.Float64:
   147  		return v.Float() == 0
   148  	case reflect.Interface, reflect.Pointer:
   149  		return v.IsNil()
   150  	default: // @diff
   151  		return v.IsZero()
   152  	}
   153  	return false
   154  }
   155  
   156  func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
   157  	valueEncoder(v)(e, v, opts)
   158  }
   159  
   160  //go:generate go-option -type "encOpts"
   161  type encOpts struct {
   162  	// quoted causes primitive fields to be encoded inside JSON strings.
   163  	quoted bool
   164  	// escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
   165  	escapeHTML bool
   166  
   167  	truncateBytes        int
   168  	truncateString       int
   169  	truncateMap          int
   170  	truncateSliceOrArray int
   171  	truncateUrl          bool // truncate query and fragment in url
   172  	omitEmpty            bool
   173  }
   174  
   175  type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
   176  
   177  var encoderCache sync.Map // map[reflect.Type]encoderFunc
   178  
   179  func valueEncoder(v reflect.Value) encoderFunc {
   180  	if !v.IsValid() {
   181  		return invalidValueEncoder
   182  	}
   183  	return typeEncoder(v.Type())
   184  }
   185  
   186  func typeEncoder(t reflect.Type) encoderFunc {
   187  	if fi, ok := encoderCache.Load(t); ok {
   188  		return fi.(encoderFunc)
   189  	}
   190  
   191  	// To deal with recursive types, populate the map with an
   192  	// indirect func before we build it. This type waits on the
   193  	// real func (f) to be ready and then calls it. This indirect
   194  	// func is only used for recursive types.
   195  	var (
   196  		wg sync.WaitGroup
   197  		f  encoderFunc
   198  	)
   199  	wg.Add(1)
   200  	fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
   201  		wg.Wait()
   202  		f(e, v, opts)
   203  	}))
   204  	if loaded {
   205  		return fi.(encoderFunc)
   206  	}
   207  
   208  	// Compute the real encoder and replace the indirect func with it.
   209  	f = newTypeEncoder(t, true)
   210  	wg.Done()
   211  	encoderCache.Store(t, f)
   212  	return f
   213  }
   214  
   215  var (
   216  	marshalerType     = reflect.TypeOf((*Marshaler)(nil)).Elem()
   217  	textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
   218  )
   219  
   220  // newTypeEncoder constructs an encoderFunc for a type.
   221  // The returned encoder only checks CanAddr when allowAddr is true.
   222  func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
   223  	// If we have a non-pointer value whose type implements
   224  	// Marshaler with a value receiver, then we're better off taking
   225  	// the address of the value - otherwise we end up with an
   226  	// allocation as we cast the value to an interface.
   227  	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
   228  		return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
   229  	}
   230  	if t.Implements(marshalerType) {
   231  		return marshalerEncoder
   232  	}
   233  	if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
   234  		return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
   235  	}
   236  	if t.Implements(textMarshalerType) {
   237  		return textMarshalerEncoder
   238  	}
   239  
   240  	switch t.Kind() {
   241  	case reflect.Bool:
   242  		return boolEncoder
   243  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   244  		return intEncoder
   245  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   246  		return uintEncoder
   247  	case reflect.Float32:
   248  		return float32Encoder
   249  	case reflect.Float64:
   250  		return float64Encoder
   251  	case reflect.String:
   252  		return stringEncoder
   253  	case reflect.Interface:
   254  		return interfaceEncoder
   255  	case reflect.Struct:
   256  		return newStructEncoder(t)
   257  	case reflect.Map:
   258  		return newMapEncoder(t)
   259  	case reflect.Slice:
   260  		return newSliceEncoder(t)
   261  	case reflect.Array:
   262  		return newArrayEncoder(t)
   263  	case reflect.Pointer:
   264  		return newPtrEncoder(t)
   265  	default:
   266  		return unsupportedTypeEncoder
   267  	}
   268  }
   269  
   270  func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
   271  	e.WriteString("null")
   272  }
   273  
   274  func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   275  	if v.Kind() == reflect.Pointer && v.IsNil() {
   276  		e.WriteString("null")
   277  		return
   278  	}
   279  	m, ok := v.Interface().(Marshaler)
   280  	if !ok {
   281  		e.WriteString("null")
   282  		return
   283  	}
   284  	b, err := m.MarshalJSON()
   285  	if err == nil {
   286  		e.Grow(len(b))
   287  		out := e.AvailableBuffer()
   288  		out, err = appendCompact(out, b, opts.escapeHTML)
   289  		e.Buffer.Write(out)
   290  	}
   291  	if err != nil {
   292  		e.error(&MarshalerError{Type: v.Type(), Err: err})
   293  	}
   294  }
   295  
   296  func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   297  	va := v.Addr()
   298  	if va.IsNil() {
   299  		e.WriteString("null")
   300  		return
   301  	}
   302  	m := va.Interface().(Marshaler)
   303  	b, err := m.MarshalJSON()
   304  	if err == nil {
   305  		e.Grow(len(b))
   306  		out := e.AvailableBuffer()
   307  		out, err = appendCompact(out, b, opts.escapeHTML)
   308  		e.Buffer.Write(out)
   309  	}
   310  	if err != nil {
   311  		e.error(&MarshalerError{Type: v.Type(), Err: err})
   312  	}
   313  }
   314  
   315  func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   316  	if v.Kind() == reflect.Pointer && v.IsNil() {
   317  		e.WriteString("null")
   318  		return
   319  	}
   320  	m, ok := v.Interface().(encoding.TextMarshaler)
   321  	if !ok {
   322  		e.WriteString("null")
   323  		return
   324  	}
   325  	b, err := m.MarshalText()
   326  	if err != nil {
   327  		e.error(&MarshalerError{Type: v.Type(), Err: err})
   328  	}
   329  	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
   330  }
   331  
   332  func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   333  	va := v.Addr()
   334  	if va.IsNil() {
   335  		e.WriteString("null")
   336  		return
   337  	}
   338  	m := va.Interface().(encoding.TextMarshaler)
   339  	b, err := m.MarshalText()
   340  	if err != nil {
   341  		e.error(&MarshalerError{Type: v.Type(), Err: err})
   342  	}
   343  	e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
   344  }
   345  
   346  func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   347  	b := e.AvailableBuffer()
   348  	b = mayAppendQuote(b, opts.quoted)
   349  	b = strconv.AppendBool(b, v.Bool())
   350  	b = mayAppendQuote(b, opts.quoted)
   351  	e.Write(b)
   352  }
   353  
   354  func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   355  	b := e.AvailableBuffer()
   356  	b = mayAppendQuote(b, opts.quoted)
   357  	b = strconv.AppendInt(b, v.Int(), 10)
   358  	b = mayAppendQuote(b, opts.quoted)
   359  	e.Write(b)
   360  }
   361  
   362  func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   363  	b := e.AvailableBuffer()
   364  	b = mayAppendQuote(b, opts.quoted)
   365  	b = strconv.AppendUint(b, v.Uint(), 10)
   366  	b = mayAppendQuote(b, opts.quoted)
   367  	e.Write(b)
   368  }
   369  
   370  type floatEncoder int // number of bits
   371  
   372  func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   373  	f := v.Float()
   374  	if math.IsInf(f, 0) || math.IsNaN(f) {
   375  		e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
   376  	}
   377  
   378  	// Convert as if by ES6 number to string conversion.
   379  	// This matches most other JSON generators.
   380  	// See golang.org/issue/6384 and golang.org/issue/14135.
   381  	// Like fmt %g, but the exponent cutoffs are different
   382  	// and exponents themselves are not padded to two digits.
   383  	b := e.AvailableBuffer()
   384  	b = mayAppendQuote(b, opts.quoted)
   385  	abs := math.Abs(f)
   386  	fmt := byte('f')
   387  	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
   388  	if abs != 0 {
   389  		if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
   390  			fmt = 'e'
   391  		}
   392  	}
   393  	b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
   394  	if fmt == 'e' {
   395  		// clean up e-09 to e-9
   396  		n := len(b)
   397  		if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
   398  			b[n-2] = b[n-1]
   399  			b = b[:n-1]
   400  		}
   401  	}
   402  	b = mayAppendQuote(b, opts.quoted)
   403  	e.Write(b)
   404  }
   405  
   406  var (
   407  	float32Encoder = (floatEncoder(32)).encode
   408  	float64Encoder = (floatEncoder(64)).encode
   409  )
   410  
   411  func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   412  	if v.Type() == numberType {
   413  		numStr := v.String()
   414  		// In Go1.5 the empty string encodes to "0", while this is not a valid number literal
   415  		// we keep compatibility so check validity after this.
   416  		if numStr == "" {
   417  			numStr = "0" // Number's zero-val
   418  		}
   419  		if !isValidNumber(numStr) {
   420  			e.error(fmt.Errorf("json: invalid number literal %q", numStr))
   421  		}
   422  		b := e.AvailableBuffer()
   423  		b = mayAppendQuote(b, opts.quoted)
   424  		b = append(b, numStr...)
   425  		b = mayAppendQuote(b, opts.quoted)
   426  		e.Write(b)
   427  		return
   428  	}
   429  	// @diff
   430  	s := v.String()
   431  	var isUrl bool
   432  	if opts.truncateUrl {
   433  		u, err := url.Parse(s)
   434  		if err == nil && u.Scheme != "" {
   435  			isUrl = true
   436  			q := u.Query()
   437  			f := u.Fragment
   438  			u.Fragment = ""
   439  			if len(q) > 0 || len(f) > 0 {
   440  				u.RawQuery = ""
   441  				u.Fragment = ""
   442  				u.RawFragment = ""
   443  				st := u.String()
   444  				st += fmt.Sprintf(" ...%d chars", len(s))
   445  				if len(q) > 0 {
   446  					st += fmt.Sprintf(",%dQ", len(q))
   447  				}
   448  				if len(f) > 0 {
   449  					st += fmt.Sprintf("%dF", len(f))
   450  				}
   451  				st += "]"
   452  				if len(st) < len(s) {
   453  					s = st
   454  				}
   455  			}
   456  		}
   457  	}
   458  
   459  	if limit := opts.truncateString; !isUrl && limit > 0 && len(s) > limit {
   460  		st := strings_.Truncate(s, limit) + fmt.Sprintf("...%d chars", len(s))
   461  		if len(st) < len(s) {
   462  			s = st
   463  		}
   464  	}
   465  	if opts.quoted {
   466  		b := appendString(nil, s, opts.escapeHTML)
   467  		e.Write(appendString(e.AvailableBuffer(), b, false)) // no need to escape again since it is already escaped
   468  	} else {
   469  		e.Write(appendString(e.AvailableBuffer(), s, opts.escapeHTML))
   470  	}
   471  }
   472  
   473  // isValidNumber reports whether s is a valid JSON number literal.
   474  func isValidNumber(s string) bool {
   475  	// This function implements the JSON numbers grammar.
   476  	// See https://tools.ietf.org/html/rfc7159#section-6
   477  	// and https://www.json.org/img/number.png
   478  
   479  	if s == "" {
   480  		return false
   481  	}
   482  
   483  	// Optional -
   484  	if s[0] == '-' {
   485  		s = s[1:]
   486  		if s == "" {
   487  			return false
   488  		}
   489  	}
   490  
   491  	// Digits
   492  	switch {
   493  	default:
   494  		return false
   495  
   496  	case s[0] == '0':
   497  		s = s[1:]
   498  
   499  	case '1' <= s[0] && s[0] <= '9':
   500  		s = s[1:]
   501  		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
   502  			s = s[1:]
   503  		}
   504  	}
   505  
   506  	// . followed by 1 or more digits.
   507  	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
   508  		s = s[2:]
   509  		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
   510  			s = s[1:]
   511  		}
   512  	}
   513  
   514  	// e or E followed by an optional - or + and
   515  	// 1 or more digits.
   516  	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
   517  		s = s[1:]
   518  		if s[0] == '+' || s[0] == '-' {
   519  			s = s[1:]
   520  			if s == "" {
   521  				return false
   522  			}
   523  		}
   524  		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
   525  			s = s[1:]
   526  		}
   527  	}
   528  
   529  	// Make sure we are at the end.
   530  	return s == ""
   531  }
   532  
   533  func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
   534  	if v.IsNil() {
   535  		e.WriteString("null")
   536  		return
   537  	}
   538  	e.reflectValue(v.Elem(), opts)
   539  }
   540  
   541  func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
   542  	e.error(&UnsupportedTypeError{v.Type()})
   543  }
   544  
   545  type structEncoder struct {
   546  	fields structFields
   547  }
   548  
   549  type structFields struct {
   550  	list         []field
   551  	byExactName  map[string]*field
   552  	byFoldedName map[string]*field
   553  }
   554  
   555  func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   556  	next := byte('{')
   557  FieldLoop:
   558  	for i := range se.fields.list {
   559  		f := &se.fields.list[i]
   560  
   561  		// Find the nested struct field by following f.index.
   562  		fv := v
   563  		for _, i := range f.index {
   564  			if fv.Kind() == reflect.Pointer {
   565  				if fv.IsNil() {
   566  					continue FieldLoop
   567  				}
   568  				fv = fv.Elem()
   569  			}
   570  			fv = fv.Field(i)
   571  		}
   572  
   573  		// @diff
   574  		if (f.omitEmpty || opts.omitEmpty) && isEmptyValue(fv) {
   575  			continue
   576  		}
   577  		e.WriteByte(next)
   578  		next = ','
   579  		if opts.escapeHTML {
   580  			e.WriteString(f.nameEscHTML)
   581  		} else {
   582  			e.WriteString(f.nameNonEsc)
   583  		}
   584  		opts.quoted = f.quoted
   585  		f.encoder(e, fv, opts)
   586  	}
   587  	if next == '{' {
   588  		e.WriteString("{}")
   589  	} else {
   590  		e.WriteByte('}')
   591  	}
   592  }
   593  
   594  func newStructEncoder(t reflect.Type) encoderFunc {
   595  	se := structEncoder{fields: cachedTypeFields(t)}
   596  	return se.encode
   597  }
   598  
   599  type mapEncoder struct {
   600  	elemEnc encoderFunc
   601  }
   602  
   603  func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   604  	if v.IsNil() {
   605  		e.WriteString("null")
   606  		return
   607  	}
   608  	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
   609  		// We're a large number of nested ptrEncoder.encode calls deep;
   610  		// start checking if we've run into a pointer cycle.
   611  		ptr := v.UnsafePointer()
   612  		if _, ok := e.ptrSeen[ptr]; ok {
   613  			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
   614  		}
   615  		e.ptrSeen[ptr] = struct{}{}
   616  		defer delete(e.ptrSeen, ptr)
   617  	}
   618  	e.WriteByte('{')
   619  
   620  	// Extract and sort the keys.
   621  	sv := make([]reflectWithString, v.Len())
   622  	mi := v.MapRange()
   623  	for i := 0; mi.Next(); i++ {
   624  		sv[i].k = mi.Key()
   625  		sv[i].v = mi.Value()
   626  		if err := sv[i].resolve(); err != nil {
   627  			e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
   628  		}
   629  	}
   630  	sort.Slice(sv, func(i, j int) bool { return sv[i].ks < sv[j].ks })
   631  
   632  	// @diff
   633  	n := len(sv)
   634  	var m string
   635  	if limit := opts.truncateMap; limit > 0 && n > limit+1 {
   636  		m = fmt.Sprintf("...%d pairs", n)
   637  		n = limit
   638  	}
   639  
   640  	var j int
   641  	for i, kv := range sv {
   642  		if j >= n {
   643  			break
   644  		}
   645  		j++
   646  		if i > 0 {
   647  			e.WriteByte(',')
   648  		}
   649  		e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
   650  		e.WriteByte(':')
   651  		me.elemEnc(e, kv.v, opts)
   652  	}
   653  	if m != "" {
   654  		if n > 0 {
   655  			e.WriteByte(',')
   656  		}
   657  		e.Write(appendString(e.AvailableBuffer(), m, opts.escapeHTML))
   658  		e.WriteByte(':')
   659  		e.Write(appendString(e.AvailableBuffer(), fmt.Sprintf("%d", len(sv)), opts.escapeHTML))
   660  	}
   661  	e.WriteByte('}')
   662  	e.ptrLevel--
   663  }
   664  
   665  func newMapEncoder(t reflect.Type) encoderFunc {
   666  	switch t.Key().Kind() {
   667  	case reflect.String,
   668  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   669  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   670  	default:
   671  		if !t.Key().Implements(textMarshalerType) {
   672  			return unsupportedTypeEncoder
   673  		}
   674  	}
   675  	me := mapEncoder{typeEncoder(t.Elem())}
   676  	return me.encode
   677  }
   678  
   679  func encodeByteSlice(e *encodeState, v reflect.Value, opts encOpts) {
   680  	if v.IsNil() {
   681  		e.WriteString("null")
   682  		return
   683  	}
   684  	s := v.Bytes()
   685  	// @diff
   686  
   687  	var m string
   688  	var st []byte
   689  	var encodedLenT int
   690  	encodedLenS := base64.StdEncoding.EncodedLen(len(s))
   691  	if limit := opts.truncateBytes; limit > 0 && len(s) > limit {
   692  		m = fmt.Sprintf("...%d bytes", len(s))
   693  		st = bytes_.Truncate(s, limit)
   694  		encodedLenT = base64.StdEncoding.EncodedLen(len(st))
   695  	}
   696  	var encodedLen int
   697  	if m != "" && len(m)+encodedLenT < encodedLenS {
   698  		encodedLen = encodedLenT
   699  		s = st
   700  	} else {
   701  		encodedLen = encodedLenS
   702  		m = ""
   703  	}
   704  
   705  	e.Grow(len(`"`) + encodedLen + len(`"`))
   706  
   707  	// TODO(https://go.dev/issue/53693): Use base64.Encoding.AppendEncode.
   708  	b := e.AvailableBuffer()
   709  	b = append(b, '"')
   710  	base64.StdEncoding.Encode(b[len(b):][:encodedLen], s)
   711  	b = b[:len(b)+encodedLen]
   712  	b = append(b, m...)
   713  	b = append(b, '"')
   714  	e.Write(b)
   715  }
   716  
   717  // sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
   718  type sliceEncoder struct {
   719  	arrayEnc encoderFunc
   720  }
   721  
   722  func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   723  	if v.IsNil() {
   724  		e.WriteString("null")
   725  		return
   726  	}
   727  	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
   728  		// We're a large number of nested ptrEncoder.encode calls deep;
   729  		// start checking if we've run into a pointer cycle.
   730  		// Here we use a struct to memorize the pointer to the first element of the slice
   731  		// and its length.
   732  		ptr := struct {
   733  			ptr any // always an unsafe.Pointer, but avoids a dependency on package unsafe
   734  			len int
   735  		}{v.UnsafePointer(), v.Len()}
   736  		if _, ok := e.ptrSeen[ptr]; ok {
   737  			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
   738  		}
   739  		e.ptrSeen[ptr] = struct{}{}
   740  		defer delete(e.ptrSeen, ptr)
   741  	}
   742  	se.arrayEnc(e, v, opts)
   743  	e.ptrLevel--
   744  }
   745  
   746  func newSliceEncoder(t reflect.Type) encoderFunc {
   747  	// Byte slices get special treatment; arrays don't.
   748  	if t.Elem().Kind() == reflect.Uint8 {
   749  		p := reflect.PointerTo(t.Elem())
   750  		if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
   751  			return encodeByteSlice
   752  		}
   753  	}
   754  	enc := sliceEncoder{newArrayEncoder(t)}
   755  	return enc.encode
   756  }
   757  
   758  type arrayEncoder struct {
   759  	elemEnc encoderFunc
   760  }
   761  
   762  func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   763  	e.WriteByte('[')
   764  	n := v.Len()
   765  	var m string
   766  	if limit := opts.truncateSliceOrArray; limit > 0 && n > limit+1 {
   767  		m = fmt.Sprintf(", \"...%d elems\"", n)
   768  		n = limit
   769  	}
   770  	for i := 0; i < n; i++ {
   771  		if i > 0 {
   772  			e.WriteByte(',')
   773  		}
   774  		ae.elemEnc(e, v.Index(i), opts)
   775  	}
   776  	if m != "" {
   777  		e.WriteString(m)
   778  	}
   779  	e.WriteByte(']')
   780  }
   781  
   782  func newArrayEncoder(t reflect.Type) encoderFunc {
   783  	enc := arrayEncoder{typeEncoder(t.Elem())}
   784  	return enc.encode
   785  }
   786  
   787  type ptrEncoder struct {
   788  	elemEnc encoderFunc
   789  }
   790  
   791  func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   792  	if v.IsNil() {
   793  		e.WriteString("null")
   794  		return
   795  	}
   796  	if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
   797  		// We're a large number of nested ptrEncoder.encode calls deep;
   798  		// start checking if we've run into a pointer cycle.
   799  		ptr := v.Interface()
   800  		if _, ok := e.ptrSeen[ptr]; ok {
   801  			e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
   802  		}
   803  		e.ptrSeen[ptr] = struct{}{}
   804  		defer delete(e.ptrSeen, ptr)
   805  	}
   806  	pe.elemEnc(e, v.Elem(), opts)
   807  	e.ptrLevel--
   808  }
   809  
   810  func newPtrEncoder(t reflect.Type) encoderFunc {
   811  	enc := ptrEncoder{typeEncoder(t.Elem())}
   812  	return enc.encode
   813  }
   814  
   815  type condAddrEncoder struct {
   816  	canAddrEnc, elseEnc encoderFunc
   817  }
   818  
   819  func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
   820  	if v.CanAddr() {
   821  		ce.canAddrEnc(e, v, opts)
   822  	} else {
   823  		ce.elseEnc(e, v, opts)
   824  	}
   825  }
   826  
   827  // newCondAddrEncoder returns an encoder that checks whether its value
   828  // CanAddr and delegates to canAddrEnc if so, else to elseEnc.
   829  func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
   830  	enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
   831  	return enc.encode
   832  }
   833  
   834  func isValidTag(s string) bool {
   835  	if s == "" {
   836  		return false
   837  	}
   838  	for _, c := range s {
   839  		switch {
   840  		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
   841  			// Backslash and quote chars are reserved, but
   842  			// otherwise any punctuation chars are allowed
   843  			// in a tag name.
   844  		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
   845  			return false
   846  		}
   847  	}
   848  	return true
   849  }
   850  
   851  func typeByIndex(t reflect.Type, index []int) reflect.Type {
   852  	for _, i := range index {
   853  		if t.Kind() == reflect.Pointer {
   854  			t = t.Elem()
   855  		}
   856  		t = t.Field(i).Type
   857  	}
   858  	return t
   859  }
   860  
   861  type reflectWithString struct {
   862  	k  reflect.Value
   863  	v  reflect.Value
   864  	ks string
   865  }
   866  
   867  func (w *reflectWithString) resolve() error {
   868  	if w.k.Kind() == reflect.String {
   869  		w.ks = w.k.String()
   870  		return nil
   871  	}
   872  	if tm, ok := w.k.Interface().(encoding.TextMarshaler); ok {
   873  		if w.k.Kind() == reflect.Pointer && w.k.IsNil() {
   874  			return nil
   875  		}
   876  		buf, err := tm.MarshalText()
   877  		w.ks = string(buf)
   878  		return err
   879  	}
   880  	switch w.k.Kind() {
   881  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   882  		w.ks = strconv.FormatInt(w.k.Int(), 10)
   883  		return nil
   884  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   885  		w.ks = strconv.FormatUint(w.k.Uint(), 10)
   886  		return nil
   887  	}
   888  	panic("unexpected map key type")
   889  }
   890  
   891  func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
   892  	dst = append(dst, '"')
   893  	start := 0
   894  	for i := 0; i < len(src); {
   895  		if b := src[i]; b < utf8.RuneSelf {
   896  			if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
   897  				i++
   898  				continue
   899  			}
   900  			dst = append(dst, src[start:i]...)
   901  			switch b {
   902  			case '\\', '"':
   903  				dst = append(dst, '\\', b)
   904  			case '\n':
   905  				dst = append(dst, '\\', 'n')
   906  			case '\r':
   907  				dst = append(dst, '\\', 'r')
   908  			case '\t':
   909  				dst = append(dst, '\\', 't')
   910  			default:
   911  				// This encodes bytes < 0x20 except for \t, \n and \r.
   912  				// If escapeHTML is set, it also escapes <, >, and &
   913  				// because they can lead to security holes when
   914  				// user-controlled strings are rendered into JSON
   915  				// and served to some browsers.
   916  				dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
   917  			}
   918  			i++
   919  			start = i
   920  			continue
   921  		}
   922  		// TODO(https://go.dev/issue/56948): Use generic utf8 functionality.
   923  		// For now, cast only a small portion of byte slices to a string
   924  		// so that it can be stack allocated. This slows down []byte slightly
   925  		// due to the extra copy, but keeps string performance roughly the same.
   926  		n := len(src) - i
   927  		if n > utf8.UTFMax {
   928  			n = utf8.UTFMax
   929  		}
   930  		c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
   931  		if c == utf8.RuneError && size == 1 {
   932  			dst = append(dst, src[start:i]...)
   933  			dst = append(dst, `\ufffd`...)
   934  			i += size
   935  			start = i
   936  			continue
   937  		}
   938  		// U+2028 is LINE SEPARATOR.
   939  		// U+2029 is PARAGRAPH SEPARATOR.
   940  		// They are both technically valid characters in JSON strings,
   941  		// but don't work in JSONP, which has to be evaluated as JavaScript,
   942  		// and can lead to security holes there. It is valid JSON to
   943  		// escape them, so we do so unconditionally.
   944  		// See http://timelessrepo.com/json-isnt-a-javascript-subset for discussion.
   945  		if c == '\u2028' || c == '\u2029' {
   946  			dst = append(dst, src[start:i]...)
   947  			dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
   948  			i += size
   949  			start = i
   950  			continue
   951  		}
   952  		i += size
   953  	}
   954  	dst = append(dst, src[start:]...)
   955  	dst = append(dst, '"')
   956  	return dst
   957  }
   958  
   959  // A field represents a single field found in a struct.
   960  type field struct {
   961  	name      string
   962  	nameBytes []byte // []byte(name)
   963  
   964  	nameNonEsc  string // `"` + name + `":`
   965  	nameEscHTML string // `"` + HTMLEscape(name) + `":`
   966  
   967  	tag       bool
   968  	index     []int
   969  	typ       reflect.Type
   970  	omitEmpty bool
   971  	quoted    bool
   972  
   973  	encoder encoderFunc
   974  }
   975  
   976  // byIndex sorts field by index sequence.
   977  type byIndex []field
   978  
   979  func (x byIndex) Len() int { return len(x) }
   980  
   981  func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
   982  
   983  func (x byIndex) Less(i, j int) bool {
   984  	for k, xik := range x[i].index {
   985  		if k >= len(x[j].index) {
   986  			return false
   987  		}
   988  		if xik != x[j].index[k] {
   989  			return xik < x[j].index[k]
   990  		}
   991  	}
   992  	return len(x[i].index) < len(x[j].index)
   993  }
   994  
   995  // typeFields returns a list of fields that JSON should recognize for the given type.
   996  // The algorithm is breadth-first search over the set of structs to include - the top struct
   997  // and then any reachable anonymous structs.
   998  func typeFields(t reflect.Type) structFields {
   999  	// Anonymous fields to explore at the current level and the next.
  1000  	current := []field{}
  1001  	next := []field{{typ: t}}
  1002  
  1003  	// Count of queued names for current level and the next.
  1004  	var count, nextCount map[reflect.Type]int
  1005  
  1006  	// Types already visited at an earlier level.
  1007  	visited := map[reflect.Type]bool{}
  1008  
  1009  	// Fields found.
  1010  	var fields []field
  1011  
  1012  	// Buffer to run appendHTMLEscape on field names.
  1013  	var nameEscBuf []byte
  1014  
  1015  	for len(next) > 0 {
  1016  		current, next = next, current[:0]
  1017  		count, nextCount = nextCount, map[reflect.Type]int{}
  1018  
  1019  		for _, f := range current {
  1020  			if visited[f.typ] {
  1021  				continue
  1022  			}
  1023  			visited[f.typ] = true
  1024  
  1025  			// Scan f.typ for fields to include.
  1026  			for i := 0; i < f.typ.NumField(); i++ {
  1027  				sf := f.typ.Field(i)
  1028  				if sf.Anonymous {
  1029  					t := sf.Type
  1030  					if t.Kind() == reflect.Pointer {
  1031  						t = t.Elem()
  1032  					}
  1033  					if !sf.IsExported() && t.Kind() != reflect.Struct {
  1034  						// Ignore embedded fields of unexported non-struct types.
  1035  						continue
  1036  					}
  1037  					// Do not ignore embedded fields of unexported struct types
  1038  					// since they may have exported fields.
  1039  				} else if !sf.IsExported() {
  1040  					// Ignore unexported non-embedded fields.
  1041  					continue
  1042  				}
  1043  				tag := sf.Tag.Get("json")
  1044  				if tag == "-" {
  1045  					continue
  1046  				}
  1047  				name, opts := parseTag(tag)
  1048  				if !isValidTag(name) {
  1049  					name = ""
  1050  				}
  1051  				index := make([]int, len(f.index)+1)
  1052  				copy(index, f.index)
  1053  				index[len(f.index)] = i
  1054  
  1055  				ft := sf.Type
  1056  				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
  1057  					// Follow pointer.
  1058  					ft = ft.Elem()
  1059  				}
  1060  
  1061  				// Only strings, floats, integers, and booleans can be quoted.
  1062  				quoted := false
  1063  				if opts.Contains("string") {
  1064  					switch ft.Kind() {
  1065  					case reflect.Bool,
  1066  						reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  1067  						reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
  1068  						reflect.Float32, reflect.Float64,
  1069  						reflect.String:
  1070  						quoted = true
  1071  					}
  1072  				}
  1073  
  1074  				// Record found field and index sequence.
  1075  				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
  1076  					tagged := name != ""
  1077  					if name == "" {
  1078  						name = sf.Name
  1079  					}
  1080  					field := field{
  1081  						name:      name,
  1082  						tag:       tagged,
  1083  						index:     index,
  1084  						typ:       ft,
  1085  						omitEmpty: opts.Contains("omitempty"),
  1086  						quoted:    quoted,
  1087  					}
  1088  					field.nameBytes = []byte(field.name)
  1089  
  1090  					// Build nameEscHTML and nameNonEsc ahead of time.
  1091  					nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
  1092  					field.nameEscHTML = `"` + string(nameEscBuf) + `":`
  1093  					field.nameNonEsc = `"` + field.name + `":`
  1094  
  1095  					fields = append(fields, field)
  1096  					if count[f.typ] > 1 {
  1097  						// If there were multiple instances, add a second,
  1098  						// so that the annihilation code will see a duplicate.
  1099  						// It only cares about the distinction between 1 or 2,
  1100  						// so don't bother generating any more copies.
  1101  						fields = append(fields, fields[len(fields)-1])
  1102  					}
  1103  					continue
  1104  				}
  1105  
  1106  				// Record new anonymous struct to explore in next round.
  1107  				nextCount[ft]++
  1108  				if nextCount[ft] == 1 {
  1109  					next = append(next, field{name: ft.Name(), index: index, typ: ft})
  1110  				}
  1111  			}
  1112  		}
  1113  	}
  1114  
  1115  	sort.Slice(fields, func(i, j int) bool {
  1116  		x := fields
  1117  		// sort field by name, breaking ties with depth, then
  1118  		// breaking ties with "name came from json tag", then
  1119  		// breaking ties with index sequence.
  1120  		if x[i].name != x[j].name {
  1121  			return x[i].name < x[j].name
  1122  		}
  1123  		if len(x[i].index) != len(x[j].index) {
  1124  			return len(x[i].index) < len(x[j].index)
  1125  		}
  1126  		if x[i].tag != x[j].tag {
  1127  			return x[i].tag
  1128  		}
  1129  		return byIndex(x).Less(i, j)
  1130  	})
  1131  
  1132  	// Delete all fields that are hidden by the Go rules for embedded fields,
  1133  	// except that fields with JSON tags are promoted.
  1134  
  1135  	// The fields are sorted in primary order of name, secondary order
  1136  	// of field index length. Loop over names; for each name, delete
  1137  	// hidden fields by choosing the one dominant field that survives.
  1138  	out := fields[:0]
  1139  	for advance, i := 0, 0; i < len(fields); i += advance {
  1140  		// One iteration per name.
  1141  		// Find the sequence of fields with the name of this first field.
  1142  		fi := fields[i]
  1143  		name := fi.name
  1144  		for advance = 1; i+advance < len(fields); advance++ {
  1145  			fj := fields[i+advance]
  1146  			if fj.name != name {
  1147  				break
  1148  			}
  1149  		}
  1150  		if advance == 1 { // Only one field with this name
  1151  			out = append(out, fi)
  1152  			continue
  1153  		}
  1154  		dominant, ok := dominantField(fields[i : i+advance])
  1155  		if ok {
  1156  			out = append(out, dominant)
  1157  		}
  1158  	}
  1159  
  1160  	fields = out
  1161  	sort.Sort(byIndex(fields))
  1162  
  1163  	for i := range fields {
  1164  		f := &fields[i]
  1165  		f.encoder = typeEncoder(typeByIndex(t, f.index))
  1166  	}
  1167  	exactNameIndex := make(map[string]*field, len(fields))
  1168  	foldedNameIndex := make(map[string]*field, len(fields))
  1169  	for i, field := range fields {
  1170  		exactNameIndex[field.name] = &fields[i]
  1171  		// For historical reasons, first folded match takes precedence.
  1172  		if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
  1173  			foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
  1174  		}
  1175  	}
  1176  	return structFields{fields, exactNameIndex, foldedNameIndex}
  1177  }
  1178  
  1179  // dominantField looks through the fields, all of which are known to
  1180  // have the same name, to find the single field that dominates the
  1181  // others using Go's embedding rules, modified by the presence of
  1182  // JSON tags. If there are multiple top-level fields, the boolean
  1183  // will be false: This condition is an error in Go and we skip all
  1184  // the fields.
  1185  func dominantField(fields []field) (field, bool) {
  1186  	// The fields are sorted in increasing index-length order, then by presence of tag.
  1187  	// That means that the first field is the dominant one. We need only check
  1188  	// for error cases: two fields at top level, either both tagged or neither tagged.
  1189  	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
  1190  		return field{}, false
  1191  	}
  1192  	return fields[0], true
  1193  }
  1194  
  1195  var fieldCache sync.Map // map[reflect.Type]structFields
  1196  
  1197  // cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
  1198  func cachedTypeFields(t reflect.Type) structFields {
  1199  	if f, ok := fieldCache.Load(t); ok {
  1200  		return f.(structFields)
  1201  	}
  1202  	f, _ := fieldCache.LoadOrStore(t, typeFields(t))
  1203  	return f.(structFields)
  1204  }
  1205  
  1206  func mayAppendQuote(b []byte, quoted bool) []byte {
  1207  	if quoted {
  1208  		b = append(b, '"')
  1209  	}
  1210  	return b
  1211  }