Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/encoding/json/jsontext/encode.go

     1  // Copyright 2020 The Go Authors. 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  //go:build goexperiment.jsonv2
     6  
     7  package jsontext
     8  
     9  import (
    10  	"bytes"
    11  	"io"
    12  	"math/bits"
    13  
    14  	"encoding/json/internal/jsonflags"
    15  	"encoding/json/internal/jsonopts"
    16  	"encoding/json/internal/jsonwire"
    17  )
    18  
    19  // Encoder is a streaming encoder to raw JSON tokens and values.
    20  // It is used to write a stream of top-level JSON values,
    21  // each terminated with a newline character.
    22  //
    23  // [Encoder.WriteToken] and [Encoder.WriteValue] calls may be interleaved.
    24  // For example, the following JSON value:
    25  //
    26  //	{"name":"value","array":[null,false,true,3.14159],"object":{"k":"v"}}
    27  //
    28  // can be composed with the following calls (ignoring errors for brevity):
    29  //
    30  //	e.WriteToken(BeginObject)        // {
    31  //	e.WriteToken(String("name"))     // "name"
    32  //	e.WriteToken(String("value"))    // "value"
    33  //	e.WriteValue(Value(`"array"`))   // "array"
    34  //	e.WriteToken(BeginArray)         // [
    35  //	e.WriteToken(Null)               // null
    36  //	e.WriteToken(False)              // false
    37  //	e.WriteValue(Value("true"))      // true
    38  //	e.WriteToken(Float(3.14159))     // 3.14159
    39  //	e.WriteToken(EndArray)           // ]
    40  //	e.WriteValue(Value(`"object"`))  // "object"
    41  //	e.WriteValue(Value(`{"k":"v"}`)) // {"k":"v"}
    42  //	e.WriteToken(EndObject)          // }
    43  //
    44  // The above is one of many possible sequences of calls and
    45  // may not represent the most sensible method to call for any given token/value.
    46  // For example, it is probably more common to call [Encoder.WriteToken] with a string
    47  // for object names.
    48  type Encoder struct {
    49  	s encoderState
    50  }
    51  
    52  // encoderState is the low-level state of Encoder.
    53  // It has exported fields and methods for use by the "json" package.
    54  type encoderState struct {
    55  	state
    56  	encodeBuffer
    57  	jsonopts.Struct
    58  
    59  	SeenPointers map[any]struct{} // only used when marshaling; identical to json.seenPointers
    60  }
    61  
    62  // encodeBuffer is a buffer split into 2 segments:
    63  //
    64  //   - buf[0:len(buf)]        // written (but unflushed) portion of the buffer
    65  //   - buf[len(buf):cap(buf)] // unused portion of the buffer
    66  type encodeBuffer struct {
    67  	Buf []byte // may alias wr if it is a bytes.Buffer
    68  
    69  	// baseOffset is added to len(buf) to obtain the absolute offset
    70  	// relative to the start of io.Writer stream.
    71  	baseOffset int64
    72  
    73  	wr io.Writer
    74  
    75  	// maxValue is the approximate maximum Value size passed to WriteValue.
    76  	maxValue int
    77  	// availBuffer is the buffer returned by the AvailableBuffer method.
    78  	availBuffer []byte // always has zero length
    79  	// bufStats is statistics about buffer utilization.
    80  	// It is only used with pooled encoders in pools.go.
    81  	bufStats bufferStatistics
    82  }
    83  
    84  // NewEncoder constructs a new streaming encoder writing to w
    85  // configured with the provided options.
    86  // It flushes the internal buffer when the buffer is sufficiently full or
    87  // when a top-level value has been written.
    88  //
    89  // If w is a [bytes.Buffer], then the encoder appends directly into the buffer
    90  // without copying the contents from an intermediate buffer.
    91  func NewEncoder(w io.Writer, opts ...Options) *Encoder {
    92  	e := new(Encoder)
    93  	e.Reset(w, opts...)
    94  	return e
    95  }
    96  
    97  // Reset resets an encoder such that it is writing afresh to w and
    98  // configured with the provided options. Reset must not be called on
    99  // an Encoder passed to the [encoding/json/v2.MarshalerTo.MarshalJSONTo] method
   100  // or the [encoding/json/v2.MarshalToFunc] function.
   101  func (e *Encoder) Reset(w io.Writer, opts ...Options) {
   102  	switch {
   103  	case e == nil:
   104  		panic("jsontext: invalid nil Encoder")
   105  	case w == nil:
   106  		// Reset with nil io.Writer is often used to avoid pinning memory
   107  		// when using the Encoder with a sync.Pool.
   108  		// A nil io.Writer is insufficient since that signals that the
   109  		// Encoder is operating in a purely buffered mode.
   110  		// Instead, use a wrapped nil interface so that method calls
   111  		// on Encoder eventually panic when calling the Write method.
   112  		w = struct{ io.Writer }{}
   113  	case e.s.Flags.Get(jsonflags.WithinArshalCall):
   114  		panic("jsontext: cannot reset Encoder passed to json.MarshalerTo")
   115  	}
   116  	// Reuse the buffer if it does not alias a previous [bytes.Buffer].
   117  	b := e.s.Buf[:0]
   118  	if _, ok := e.s.wr.(*bytes.Buffer); ok {
   119  		b = nil
   120  	}
   121  	e.s.reset(b, w, opts...)
   122  }
   123  
   124  func (e *encoderState) reset(b []byte, w io.Writer, opts ...Options) {
   125  	e.state.reset()
   126  	e.encodeBuffer = encodeBuffer{Buf: b, wr: w, availBuffer: e.availBuffer, bufStats: e.bufStats}
   127  	if bb, ok := w.(*bytes.Buffer); ok && bb != nil {
   128  		e.Buf = bb.AvailableBuffer() // alias the unused buffer of bb
   129  	}
   130  	opts2 := jsonopts.Struct{} // avoid mutating e.Struct in case it is part of opts
   131  	opts2.Join(opts...)
   132  	e.Struct = opts2
   133  	if e.Struct.Flags.Get(jsonflags.Multiline) {
   134  		e.Struct.InitializeMultiline()
   135  	}
   136  }
   137  
   138  // Options returns the options used to construct the encoder and
   139  // may additionally contain semantic options passed to a
   140  // [encoding/json/v2.MarshalEncode] call.
   141  //
   142  // If operating within
   143  // a [encoding/json/v2.MarshalerTo.MarshalJSONTo] method call or
   144  // a [encoding/json/v2.MarshalToFunc] function call,
   145  // then the returned options are only valid within the call.
   146  func (e *Encoder) Options() Options {
   147  	return &e.s.Struct
   148  }
   149  
   150  func (e *encoderState) options() *jsonopts.Struct { return &e.Struct }
   151  
   152  // NeedFlush determines whether to flush at this point.
   153  func (e *encoderState) NeedFlush() bool {
   154  	// NOTE: This function is carefully written to be inlinable.
   155  
   156  	// Avoid flushing if e.wr is nil since there is no underlying writer.
   157  	// Flush if less than 25% of the capacity remains.
   158  	// Flushing at some constant fraction ensures that the buffer stops growing
   159  	// so long as the largest Token or Value fits within that unused capacity.
   160  	return e.wr != nil && (e.Tokens.Depth() == 1 || len(e.Buf) > 3*cap(e.Buf)/4)
   161  }
   162  
   163  // Flush flushes the buffer to the underlying io.Writer.
   164  // It may append a trailing newline after the top-level value.
   165  func (e *encoderState) Flush() error {
   166  	if e.wr == nil || e.avoidFlush() {
   167  		return nil
   168  	}
   169  	if w, ok := e.wr.(struct{ io.Writer }); ok && w.Writer == nil {
   170  		panic("nil io.Writer")
   171  	}
   172  
   173  	// In streaming mode, always emit a newline after the top-level value.
   174  	if e.Tokens.Depth() == 1 && !e.Flags.Get(jsonflags.OmitTopLevelNewline) {
   175  		e.Buf = append(e.Buf, '\n')
   176  	}
   177  
   178  	// Inform objectNameStack that we are about to flush the buffer content.
   179  	e.Names.copyQuotedBuffer(e.Buf)
   180  
   181  	// Specialize bytes.Buffer for better performance.
   182  	if bb, ok := e.wr.(*bytes.Buffer); ok {
   183  		// If e.Buf already aliases the internal buffer of bb,
   184  		// then the Write call simply increments the internal offset,
   185  		// otherwise Write operates as expected.
   186  		// See https://go.dev/issue/42986.
   187  		n, _ := bb.Write(e.Buf) // never fails unless bb is nil
   188  		e.baseOffset += int64(n)
   189  
   190  		// If the internal buffer of bytes.Buffer is too small,
   191  		// append operations elsewhere in the Encoder may grow the buffer.
   192  		// This would be semantically correct, but hurts performance.
   193  		// As such, ensure 25% of the current length is always available
   194  		// to reduce the probability that other appends must allocate.
   195  		if avail := bb.Available(); avail < bb.Len()/4 {
   196  			bb.Grow(avail + 1)
   197  		}
   198  
   199  		e.Buf = bb.AvailableBuffer()
   200  		return nil
   201  	}
   202  
   203  	// Flush the internal buffer to the underlying io.Writer.
   204  	n, err := e.wr.Write(e.Buf)
   205  	e.baseOffset += int64(n)
   206  	if err != nil {
   207  		// In the event of an error, preserve the unflushed portion.
   208  		// Thus, write errors aren't fatal so long as the io.Writer
   209  		// maintains consistent state after errors.
   210  		if n > 0 {
   211  			e.Buf = e.Buf[:copy(e.Buf, e.Buf[n:])]
   212  		}
   213  		return &ioError{action: "write", err: err}
   214  	}
   215  	e.Buf = e.Buf[:0]
   216  
   217  	// Check whether to grow the buffer.
   218  	// Note that cap(e.Buf) may already exceed maxBufferSize since
   219  	// an append elsewhere already grew it to store a large token.
   220  	const maxBufferSize = 4 << 10
   221  	const growthSizeFactor = 2 // higher value is faster
   222  	const growthRateFactor = 2 // higher value is slower
   223  	// By default, grow if below the maximum buffer size.
   224  	grow := cap(e.Buf) <= maxBufferSize/growthSizeFactor
   225  	// Growing can be expensive, so only grow
   226  	// if a sufficient number of bytes have been processed.
   227  	grow = grow && int64(cap(e.Buf)) < e.previousOffsetEnd()/growthRateFactor
   228  	if grow {
   229  		e.Buf = make([]byte, 0, cap(e.Buf)*growthSizeFactor)
   230  	}
   231  
   232  	return nil
   233  }
   234  func (e *encodeBuffer) offsetAt(pos int) int64   { return e.baseOffset + int64(pos) }
   235  func (e *encodeBuffer) previousOffsetEnd() int64 { return e.baseOffset + int64(len(e.Buf)) }
   236  func (e *encodeBuffer) unflushedBuffer() []byte  { return e.Buf }
   237  
   238  // avoidFlush indicates whether to avoid flushing to ensure there is always
   239  // enough in the buffer to unwrite the last object member if it were empty.
   240  func (e *encoderState) avoidFlush() bool {
   241  	switch {
   242  	case e.Tokens.Last.Length() == 0:
   243  		// Never flush after BeginObject or BeginArray since we don't know yet
   244  		// if the object or array will end up being empty.
   245  		return true
   246  	case e.Tokens.Last.needObjectValue():
   247  		// Never flush before the object value since we don't know yet
   248  		// if the object value will end up being empty.
   249  		return true
   250  	case e.Tokens.Last.NeedObjectName() && len(e.Buf) >= 2:
   251  		// Never flush after the object value if it does turn out to be empty.
   252  		switch string(e.Buf[len(e.Buf)-2:]) {
   253  		case `ll`, `""`, `{}`, `[]`: // last two bytes of every empty value
   254  			return true
   255  		}
   256  	}
   257  	return false
   258  }
   259  
   260  // UnwriteEmptyObjectMember unwrites the last object member if it is empty
   261  // and reports whether it performed an unwrite operation.
   262  func (e *encoderState) UnwriteEmptyObjectMember(prevName *string) bool {
   263  	if last := e.Tokens.Last; !last.isObject() || !last.NeedObjectName() || last.Length() == 0 {
   264  		panic("BUG: must be called on an object after writing a value")
   265  	}
   266  
   267  	// The flushing logic is modified to never flush a trailing empty value.
   268  	// The encoder never writes trailing whitespace eagerly.
   269  	b := e.unflushedBuffer()
   270  
   271  	// Detect whether the last value was empty.
   272  	var n int
   273  	if len(b) >= 3 {
   274  		switch string(b[len(b)-2:]) {
   275  		case "ll": // last two bytes of `null`
   276  			n = len(`null`)
   277  		case `""`:
   278  			// It is possible for a non-empty string to have `""` as a suffix
   279  			// if the second to the last quote was escaped.
   280  			if b[len(b)-3] == '\\' {
   281  				return false // e.g., `"\""` is not empty
   282  			}
   283  			n = len(`""`)
   284  		case `{}`:
   285  			n = len(`{}`)
   286  		case `[]`:
   287  			n = len(`[]`)
   288  		}
   289  	}
   290  	if n == 0 {
   291  		return false
   292  	}
   293  
   294  	// Unwrite the value, whitespace, colon, name, whitespace, and comma.
   295  	b = b[:len(b)-n]
   296  	b = jsonwire.TrimSuffixWhitespace(b)
   297  	b = jsonwire.TrimSuffixByte(b, ':')
   298  	b = jsonwire.TrimSuffixString(b)
   299  	b = jsonwire.TrimSuffixWhitespace(b)
   300  	b = jsonwire.TrimSuffixByte(b, ',')
   301  	e.Buf = b // store back truncated unflushed buffer
   302  
   303  	// Undo state changes.
   304  	e.Tokens.Last.decrement() // for object member value
   305  	e.Tokens.Last.decrement() // for object member name
   306  	if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   307  		if e.Tokens.Last.isActiveNamespace() {
   308  			e.Namespaces.Last().removeLast()
   309  		}
   310  	}
   311  	e.Names.clearLast()
   312  	if prevName != nil {
   313  		e.Names.copyQuotedBuffer(e.Buf) // required by objectNameStack.replaceLastUnquotedName
   314  		e.Names.replaceLastUnquotedName(*prevName)
   315  	}
   316  	return true
   317  }
   318  
   319  // UnwriteOnlyObjectMemberName unwrites the only object member name
   320  // and returns the unquoted name.
   321  func (e *encoderState) UnwriteOnlyObjectMemberName() string {
   322  	if last := e.Tokens.Last; !last.isObject() || last.Length() != 1 {
   323  		panic("BUG: must be called on an object after writing first name")
   324  	}
   325  
   326  	// Unwrite the name and whitespace.
   327  	b := jsonwire.TrimSuffixString(e.Buf)
   328  	isVerbatim := bytes.IndexByte(e.Buf[len(b):], '\\') < 0
   329  	name := string(jsonwire.UnquoteMayCopy(e.Buf[len(b):], isVerbatim))
   330  	e.Buf = jsonwire.TrimSuffixWhitespace(b)
   331  
   332  	// Undo state changes.
   333  	e.Tokens.Last.decrement()
   334  	if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   335  		if e.Tokens.Last.isActiveNamespace() {
   336  			e.Namespaces.Last().removeLast()
   337  		}
   338  	}
   339  	e.Names.clearLast()
   340  	return name
   341  }
   342  
   343  // WriteToken writes the next token and advances the internal write offset.
   344  //
   345  // The provided token kind must be consistent with the JSON grammar.
   346  // For example, it is an error to provide a number when the encoder
   347  // is expecting an object name (which is always a string), or
   348  // to provide an end object delimiter when the encoder is finishing an array.
   349  // If the provided token is invalid, then WriteToken reports a [SyntacticError] and
   350  // the internal state remains unchanged. The offset reported
   351  // in [SyntacticError] will be the [Encoder.OutputOffset] plus any delimiter
   352  // or whitespace characters that would have preceded the provided token.
   353  func (e *Encoder) WriteToken(t Token) error {
   354  	return e.s.WriteToken(t)
   355  }
   356  func (e *encoderState) WriteToken(t Token) error {
   357  	k := t.Kind()
   358  	b := e.Buf // use local variable to avoid mutating e in case of error
   359  
   360  	// Append any delimiters or optional whitespace.
   361  	b = e.Tokens.MayAppendDelim(b, k)
   362  	if e.Flags.Get(jsonflags.AnyWhitespace) {
   363  		b = e.appendWhitespace(b, k)
   364  	}
   365  	pos := len(b) // offset before the token
   366  
   367  	// Append the token to the output and to the state machine.
   368  	var err error
   369  	switch k {
   370  	case 'n':
   371  		b = append(b, "null"...)
   372  		err = e.Tokens.appendLiteral()
   373  	case 'f':
   374  		b = append(b, "false"...)
   375  		err = e.Tokens.appendLiteral()
   376  	case 't':
   377  		b = append(b, "true"...)
   378  		err = e.Tokens.appendLiteral()
   379  	case '"':
   380  		if b, err = t.appendString(b, &e.Flags); err != nil {
   381  			break
   382  		}
   383  		if e.Tokens.Last.NeedObjectName() {
   384  			if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   385  				if !e.Tokens.Last.isValidNamespace() {
   386  					err = errInvalidNamespace
   387  					break
   388  				}
   389  				if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], false) {
   390  					err = wrapWithObjectName(ErrDuplicateName, b[pos:])
   391  					break
   392  				}
   393  			}
   394  			e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds
   395  		}
   396  		err = e.Tokens.appendString()
   397  	case '0':
   398  		if b, err = t.appendNumber(b, &e.Flags); err != nil {
   399  			break
   400  		}
   401  		err = e.Tokens.appendNumber()
   402  	case '{':
   403  		b = append(b, '{')
   404  		if err = e.Tokens.pushObject(); err != nil {
   405  			break
   406  		}
   407  		e.Names.push()
   408  		if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   409  			e.Namespaces.push()
   410  		}
   411  		e.Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth
   412  	case '}':
   413  		b = append(b, '}')
   414  		if err = e.Tokens.popObject(); err != nil {
   415  			break
   416  		}
   417  		e.Names.pop()
   418  		if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   419  			e.Namespaces.pop()
   420  		}
   421  	case '[':
   422  		b = append(b, '[')
   423  		err = e.Tokens.pushArray()
   424  		e.Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth
   425  	case ']':
   426  		b = append(b, ']')
   427  		err = e.Tokens.popArray()
   428  	default:
   429  		err = errInvalidToken
   430  	}
   431  	if err != nil {
   432  		return wrapSyntacticError(e, err, pos, +1)
   433  	}
   434  
   435  	// Finish off the buffer and store it back into e.
   436  	e.Buf = b
   437  	if e.NeedFlush() {
   438  		return e.Flush()
   439  	}
   440  	return nil
   441  }
   442  
   443  // AppendRaw appends either a raw string (without double quotes) or number.
   444  // Specify safeASCII if the string output is guaranteed to be ASCII
   445  // without any characters (including '<', '>', and '&') that need escaping,
   446  // otherwise this will validate whether the string needs escaping.
   447  // The appended bytes for a JSON number must be valid.
   448  //
   449  // This is a specialized implementation of Encoder.WriteValue
   450  // that allows appending directly into the buffer.
   451  // It is only called from marshal logic in the "json" package.
   452  func (e *encoderState) AppendRaw(k Kind, safeASCII bool, appendFn func([]byte) ([]byte, error)) error {
   453  	b := e.Buf // use local variable to avoid mutating e in case of error
   454  
   455  	// Append any delimiters or optional whitespace.
   456  	b = e.Tokens.MayAppendDelim(b, k)
   457  	if e.Flags.Get(jsonflags.AnyWhitespace) {
   458  		b = e.appendWhitespace(b, k)
   459  	}
   460  	pos := len(b) // offset before the token
   461  
   462  	var err error
   463  	switch k {
   464  	case '"':
   465  		// Append directly into the encoder buffer by assuming that
   466  		// most of the time none of the characters need escaping.
   467  		b = append(b, '"')
   468  		if b, err = appendFn(b); err != nil {
   469  			return err
   470  		}
   471  		b = append(b, '"')
   472  
   473  		// Check whether we need to escape the string and if necessary
   474  		// copy it to a scratch buffer and then escape it back.
   475  		isVerbatim := safeASCII || !jsonwire.NeedEscape(b[pos+len(`"`):len(b)-len(`"`)])
   476  		if !isVerbatim {
   477  			var err error
   478  			b2 := append(e.availBuffer, b[pos+len(`"`):len(b)-len(`"`)]...)
   479  			b, err = jsonwire.AppendQuote(b[:pos], b2, &e.Flags)
   480  			e.availBuffer = b2[:0]
   481  			if err != nil {
   482  				return wrapSyntacticError(e, err, pos, +1)
   483  			}
   484  		}
   485  
   486  		// Update the state machine.
   487  		if e.Tokens.Last.NeedObjectName() {
   488  			if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   489  				if !e.Tokens.Last.isValidNamespace() {
   490  					return wrapSyntacticError(e, errInvalidNamespace, pos, +1)
   491  				}
   492  				if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], isVerbatim) {
   493  					err = wrapWithObjectName(ErrDuplicateName, b[pos:])
   494  					return wrapSyntacticError(e, err, pos, +1)
   495  				}
   496  			}
   497  			e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds
   498  		}
   499  		if err := e.Tokens.appendString(); err != nil {
   500  			return wrapSyntacticError(e, err, pos, +1)
   501  		}
   502  	case '0':
   503  		if b, err = appendFn(b); err != nil {
   504  			return err
   505  		}
   506  		if err := e.Tokens.appendNumber(); err != nil {
   507  			return wrapSyntacticError(e, err, pos, +1)
   508  		}
   509  	default:
   510  		panic("BUG: invalid kind")
   511  	}
   512  
   513  	// Finish off the buffer and store it back into e.
   514  	e.Buf = b
   515  	if e.NeedFlush() {
   516  		return e.Flush()
   517  	}
   518  	return nil
   519  }
   520  
   521  // WriteValue writes the next raw value and advances the internal write offset.
   522  // The Encoder does not simply copy the provided value verbatim, but
   523  // parses it to ensure that it is syntactically valid and reformats it
   524  // according to how the Encoder is configured to format whitespace and strings.
   525  // If [AllowInvalidUTF8] is specified, then any invalid UTF-8 is mangled
   526  // as the Unicode replacement character, U+FFFD.
   527  //
   528  // The provided value kind must be consistent with the JSON grammar
   529  // (see examples on [Encoder.WriteToken]). If the provided value is invalid,
   530  // then WriteValue reports a [SyntacticError] and the internal state remains unchanged.
   531  // The offset reported in [SyntacticError] will be the [Encoder.OutputOffset]
   532  // plus the offset into v of any encountered syntax error.
   533  func (e *Encoder) WriteValue(v Value) error {
   534  	return e.s.WriteValue(v)
   535  }
   536  func (e *encoderState) WriteValue(v Value) error {
   537  	e.maxValue |= len(v) // bitwise OR is a fast approximation of max
   538  
   539  	k := v.Kind()
   540  	b := e.Buf // use local variable to avoid mutating e in case of error
   541  
   542  	// Append any delimiters or optional whitespace.
   543  	b = e.Tokens.MayAppendDelim(b, k)
   544  	if e.Flags.Get(jsonflags.AnyWhitespace) {
   545  		b = e.appendWhitespace(b, k)
   546  	}
   547  	pos := len(b) // offset before the value
   548  
   549  	// Append the value to the output.
   550  	var n int
   551  	n += jsonwire.ConsumeWhitespace(v[n:])
   552  	b, m, err := e.reformatValue(b, v[n:], e.Tokens.Depth())
   553  	if err != nil {
   554  		return wrapSyntacticError(e, err, pos+n+m, +1)
   555  	}
   556  	n += m
   557  	n += jsonwire.ConsumeWhitespace(v[n:])
   558  	if len(v) > n {
   559  		err = jsonwire.NewInvalidCharacterError(v[n:], "after top-level value")
   560  		return wrapSyntacticError(e, err, pos+n, 0)
   561  	}
   562  
   563  	// Append the kind to the state machine.
   564  	switch k {
   565  	case 'n', 'f', 't':
   566  		err = e.Tokens.appendLiteral()
   567  	case '"':
   568  		if e.Tokens.Last.NeedObjectName() {
   569  			if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   570  				if !e.Tokens.Last.isValidNamespace() {
   571  					err = errInvalidNamespace
   572  					break
   573  				}
   574  				if e.Tokens.Last.isActiveNamespace() && !e.Namespaces.Last().insertQuoted(b[pos:], false) {
   575  					err = wrapWithObjectName(ErrDuplicateName, b[pos:])
   576  					break
   577  				}
   578  			}
   579  			e.Names.ReplaceLastQuotedOffset(pos) // only replace if insertQuoted succeeds
   580  		}
   581  		err = e.Tokens.appendString()
   582  	case '0':
   583  		err = e.Tokens.appendNumber()
   584  	case '{':
   585  		if err = e.Tokens.pushObject(); err != nil {
   586  			break
   587  		}
   588  		if err = e.Tokens.popObject(); err != nil {
   589  			panic("BUG: popObject should never fail immediately after pushObject: " + err.Error())
   590  		}
   591  		if e.Flags.Get(jsonflags.ReorderRawObjects) {
   592  			mustReorderObjects(b[pos:])
   593  		}
   594  	case '[':
   595  		if err = e.Tokens.pushArray(); err != nil {
   596  			break
   597  		}
   598  		if err = e.Tokens.popArray(); err != nil {
   599  			panic("BUG: popArray should never fail immediately after pushArray: " + err.Error())
   600  		}
   601  		if e.Flags.Get(jsonflags.ReorderRawObjects) {
   602  			mustReorderObjects(b[pos:])
   603  		}
   604  	}
   605  	if err != nil {
   606  		return wrapSyntacticError(e, err, pos, +1)
   607  	}
   608  
   609  	// Finish off the buffer and store it back into e.
   610  	e.Buf = b
   611  	if e.NeedFlush() {
   612  		return e.Flush()
   613  	}
   614  	return nil
   615  }
   616  
   617  // CountNextDelimWhitespace counts the number of bytes of delimiter and
   618  // whitespace bytes assuming the upcoming token is a JSON value.
   619  // This method is used for error reporting at the semantic layer.
   620  func (e *encoderState) CountNextDelimWhitespace() (n int) {
   621  	const next = Kind('"') // arbitrary kind as next JSON value
   622  	delim := e.Tokens.needDelim(next)
   623  	if delim > 0 {
   624  		n += len(",") | len(":")
   625  	}
   626  	if delim == ':' {
   627  		if e.Flags.Get(jsonflags.SpaceAfterColon) {
   628  			n += len(" ")
   629  		}
   630  	} else {
   631  		if delim == ',' && e.Flags.Get(jsonflags.SpaceAfterComma) {
   632  			n += len(" ")
   633  		}
   634  		if e.Flags.Get(jsonflags.Multiline) {
   635  			if m := e.Tokens.NeedIndent(next); m > 0 {
   636  				n += len("\n") + len(e.IndentPrefix) + (m-1)*len(e.Indent)
   637  			}
   638  		}
   639  	}
   640  	return n
   641  }
   642  
   643  // appendWhitespace appends whitespace that immediately precedes the next token.
   644  func (e *encoderState) appendWhitespace(b []byte, next Kind) []byte {
   645  	if delim := e.Tokens.needDelim(next); delim == ':' {
   646  		if e.Flags.Get(jsonflags.SpaceAfterColon) {
   647  			b = append(b, ' ')
   648  		}
   649  	} else {
   650  		if delim == ',' && e.Flags.Get(jsonflags.SpaceAfterComma) {
   651  			b = append(b, ' ')
   652  		}
   653  		if e.Flags.Get(jsonflags.Multiline) {
   654  			b = e.AppendIndent(b, e.Tokens.NeedIndent(next))
   655  		}
   656  	}
   657  	return b
   658  }
   659  
   660  // AppendIndent appends the appropriate number of indentation characters
   661  // for the current nested level, n.
   662  func (e *encoderState) AppendIndent(b []byte, n int) []byte {
   663  	if n == 0 {
   664  		return b
   665  	}
   666  	b = append(b, '\n')
   667  	b = append(b, e.IndentPrefix...)
   668  	for ; n > 1; n-- {
   669  		b = append(b, e.Indent...)
   670  	}
   671  	return b
   672  }
   673  
   674  // reformatValue parses a JSON value from the start of src and
   675  // appends it to the end of dst, reformatting whitespace and strings as needed.
   676  // It returns the extended dst buffer and the number of consumed input bytes.
   677  func (e *encoderState) reformatValue(dst []byte, src Value, depth int) ([]byte, int, error) {
   678  	// TODO: Should this update ValueFlags as input?
   679  	if len(src) == 0 {
   680  		return dst, 0, io.ErrUnexpectedEOF
   681  	}
   682  	switch k := Kind(src[0]).normalize(); k {
   683  	case 'n':
   684  		if jsonwire.ConsumeNull(src) == 0 {
   685  			n, err := jsonwire.ConsumeLiteral(src, "null")
   686  			return dst, n, err
   687  		}
   688  		return append(dst, "null"...), len("null"), nil
   689  	case 'f':
   690  		if jsonwire.ConsumeFalse(src) == 0 {
   691  			n, err := jsonwire.ConsumeLiteral(src, "false")
   692  			return dst, n, err
   693  		}
   694  		return append(dst, "false"...), len("false"), nil
   695  	case 't':
   696  		if jsonwire.ConsumeTrue(src) == 0 {
   697  			n, err := jsonwire.ConsumeLiteral(src, "true")
   698  			return dst, n, err
   699  		}
   700  		return append(dst, "true"...), len("true"), nil
   701  	case '"':
   702  		if n := jsonwire.ConsumeSimpleString(src); n > 0 {
   703  			dst = append(dst, src[:n]...) // copy simple strings verbatim
   704  			return dst, n, nil
   705  		}
   706  		return jsonwire.ReformatString(dst, src, &e.Flags)
   707  	case '0':
   708  		if n := jsonwire.ConsumeSimpleNumber(src); n > 0 && !e.Flags.Get(jsonflags.CanonicalizeNumbers) {
   709  			dst = append(dst, src[:n]...) // copy simple numbers verbatim
   710  			return dst, n, nil
   711  		}
   712  		return jsonwire.ReformatNumber(dst, src, &e.Flags)
   713  	case '{':
   714  		return e.reformatObject(dst, src, depth)
   715  	case '[':
   716  		return e.reformatArray(dst, src, depth)
   717  	default:
   718  		return dst, 0, jsonwire.NewInvalidCharacterError(src, "at start of value")
   719  	}
   720  }
   721  
   722  // reformatObject parses a JSON object from the start of src and
   723  // appends it to the end of dst, reformatting whitespace and strings as needed.
   724  // It returns the extended dst buffer and the number of consumed input bytes.
   725  func (e *encoderState) reformatObject(dst []byte, src Value, depth int) ([]byte, int, error) {
   726  	// Append object begin.
   727  	if len(src) == 0 || src[0] != '{' {
   728  		panic("BUG: reformatObject must be called with a buffer that starts with '{'")
   729  	} else if depth == maxNestingDepth+1 {
   730  		return dst, 0, errMaxDepth
   731  	}
   732  	dst = append(dst, '{')
   733  	n := len("{")
   734  
   735  	// Append (possible) object end.
   736  	n += jsonwire.ConsumeWhitespace(src[n:])
   737  	if uint(len(src)) <= uint(n) {
   738  		return dst, n, io.ErrUnexpectedEOF
   739  	}
   740  	if src[n] == '}' {
   741  		dst = append(dst, '}')
   742  		n += len("}")
   743  		return dst, n, nil
   744  	}
   745  
   746  	var err error
   747  	var names *objectNamespace
   748  	if !e.Flags.Get(jsonflags.AllowDuplicateNames) {
   749  		e.Namespaces.push()
   750  		defer e.Namespaces.pop()
   751  		names = e.Namespaces.Last()
   752  	}
   753  	depth++
   754  	for {
   755  		// Append optional newline and indentation.
   756  		if e.Flags.Get(jsonflags.Multiline) {
   757  			dst = e.AppendIndent(dst, depth)
   758  		}
   759  
   760  		// Append object name.
   761  		n += jsonwire.ConsumeWhitespace(src[n:])
   762  		if uint(len(src)) <= uint(n) {
   763  			return dst, n, io.ErrUnexpectedEOF
   764  		}
   765  		m := jsonwire.ConsumeSimpleString(src[n:])
   766  		isVerbatim := m > 0
   767  		if isVerbatim {
   768  			dst = append(dst, src[n:n+m]...)
   769  		} else {
   770  			dst, m, err = jsonwire.ReformatString(dst, src[n:], &e.Flags)
   771  			if err != nil {
   772  				return dst, n + m, err
   773  			}
   774  		}
   775  		quotedName := src[n : n+m]
   776  		if !e.Flags.Get(jsonflags.AllowDuplicateNames) && !names.insertQuoted(quotedName, isVerbatim) {
   777  			return dst, n, wrapWithObjectName(ErrDuplicateName, quotedName)
   778  		}
   779  		n += m
   780  
   781  		// Append colon.
   782  		n += jsonwire.ConsumeWhitespace(src[n:])
   783  		if uint(len(src)) <= uint(n) {
   784  			return dst, n, wrapWithObjectName(io.ErrUnexpectedEOF, quotedName)
   785  		}
   786  		if src[n] != ':' {
   787  			err = jsonwire.NewInvalidCharacterError(src[n:], "after object name (expecting ':')")
   788  			return dst, n, wrapWithObjectName(err, quotedName)
   789  		}
   790  		dst = append(dst, ':')
   791  		n += len(":")
   792  		if e.Flags.Get(jsonflags.SpaceAfterColon) {
   793  			dst = append(dst, ' ')
   794  		}
   795  
   796  		// Append object value.
   797  		n += jsonwire.ConsumeWhitespace(src[n:])
   798  		if uint(len(src)) <= uint(n) {
   799  			return dst, n, wrapWithObjectName(io.ErrUnexpectedEOF, quotedName)
   800  		}
   801  		dst, m, err = e.reformatValue(dst, src[n:], depth)
   802  		if err != nil {
   803  			return dst, n + m, wrapWithObjectName(err, quotedName)
   804  		}
   805  		n += m
   806  
   807  		// Append comma or object end.
   808  		n += jsonwire.ConsumeWhitespace(src[n:])
   809  		if uint(len(src)) <= uint(n) {
   810  			return dst, n, io.ErrUnexpectedEOF
   811  		}
   812  		switch src[n] {
   813  		case ',':
   814  			dst = append(dst, ',')
   815  			if e.Flags.Get(jsonflags.SpaceAfterComma) {
   816  				dst = append(dst, ' ')
   817  			}
   818  			n += len(",")
   819  			continue
   820  		case '}':
   821  			if e.Flags.Get(jsonflags.Multiline) {
   822  				dst = e.AppendIndent(dst, depth-1)
   823  			}
   824  			dst = append(dst, '}')
   825  			n += len("}")
   826  			return dst, n, nil
   827  		default:
   828  			return dst, n, jsonwire.NewInvalidCharacterError(src[n:], "after object value (expecting ',' or '}')")
   829  		}
   830  	}
   831  }
   832  
   833  // reformatArray parses a JSON array from the start of src and
   834  // appends it to the end of dst, reformatting whitespace and strings as needed.
   835  // It returns the extended dst buffer and the number of consumed input bytes.
   836  func (e *encoderState) reformatArray(dst []byte, src Value, depth int) ([]byte, int, error) {
   837  	// Append array begin.
   838  	if len(src) == 0 || src[0] != '[' {
   839  		panic("BUG: reformatArray must be called with a buffer that starts with '['")
   840  	} else if depth == maxNestingDepth+1 {
   841  		return dst, 0, errMaxDepth
   842  	}
   843  	dst = append(dst, '[')
   844  	n := len("[")
   845  
   846  	// Append (possible) array end.
   847  	n += jsonwire.ConsumeWhitespace(src[n:])
   848  	if uint(len(src)) <= uint(n) {
   849  		return dst, n, io.ErrUnexpectedEOF
   850  	}
   851  	if src[n] == ']' {
   852  		dst = append(dst, ']')
   853  		n += len("]")
   854  		return dst, n, nil
   855  	}
   856  
   857  	var idx int64
   858  	var err error
   859  	depth++
   860  	for {
   861  		// Append optional newline and indentation.
   862  		if e.Flags.Get(jsonflags.Multiline) {
   863  			dst = e.AppendIndent(dst, depth)
   864  		}
   865  
   866  		// Append array value.
   867  		n += jsonwire.ConsumeWhitespace(src[n:])
   868  		if uint(len(src)) <= uint(n) {
   869  			return dst, n, io.ErrUnexpectedEOF
   870  		}
   871  		var m int
   872  		dst, m, err = e.reformatValue(dst, src[n:], depth)
   873  		if err != nil {
   874  			return dst, n + m, wrapWithArrayIndex(err, idx)
   875  		}
   876  		n += m
   877  
   878  		// Append comma or array end.
   879  		n += jsonwire.ConsumeWhitespace(src[n:])
   880  		if uint(len(src)) <= uint(n) {
   881  			return dst, n, io.ErrUnexpectedEOF
   882  		}
   883  		switch src[n] {
   884  		case ',':
   885  			dst = append(dst, ',')
   886  			if e.Flags.Get(jsonflags.SpaceAfterComma) {
   887  				dst = append(dst, ' ')
   888  			}
   889  			n += len(",")
   890  			idx++
   891  			continue
   892  		case ']':
   893  			if e.Flags.Get(jsonflags.Multiline) {
   894  				dst = e.AppendIndent(dst, depth-1)
   895  			}
   896  			dst = append(dst, ']')
   897  			n += len("]")
   898  			return dst, n, nil
   899  		default:
   900  			return dst, n, jsonwire.NewInvalidCharacterError(src[n:], "after array value (expecting ',' or ']')")
   901  		}
   902  	}
   903  }
   904  
   905  // OutputOffset returns the current output byte offset. It gives the location
   906  // of the next byte immediately after the most recently written token or value.
   907  // The number of bytes actually written to the underlying [io.Writer] may be less
   908  // than this offset due to internal buffering.
   909  func (e *Encoder) OutputOffset() int64 {
   910  	return e.s.previousOffsetEnd()
   911  }
   912  
   913  // AvailableBuffer returns a zero-length buffer with a possible non-zero capacity.
   914  // This buffer is intended to be used to populate a [Value]
   915  // being passed to an immediately succeeding [Encoder.WriteValue] call.
   916  //
   917  // Example usage:
   918  //
   919  //	b := e.AvailableBuffer()
   920  //	b = append(b, '"')
   921  //	b = appendString(b, v) // append the string formatting of v
   922  //	b = append(b, '"')
   923  //	... := e.WriteValue(b)
   924  //
   925  // Note that WriteValue expects a valid JSON value. Constructing a value in a
   926  // raw []byte requires more care than using constructor functions like
   927  // [String], which always return valid [Token]s or [Value]s.
   928  func (e *Encoder) AvailableBuffer() []byte {
   929  	// NOTE: We don't return e.Buf[len(e.Buf):cap(e.Buf)] since WriteValue would
   930  	// need to take special care to avoid mangling the data while reformatting.
   931  	// WriteValue can't easily identify whether the input Value aliases e.Buf
   932  	// without using unsafe.Pointer. Thus, we just return a different buffer.
   933  	// Should this ever alias e.Buf, we need to consider how it operates with
   934  	// the specialized performance optimization for bytes.Buffer.
   935  	n := 1 << bits.Len(uint(e.s.maxValue|63)) // fast approximation for max length
   936  	if cap(e.s.availBuffer) < n {
   937  		e.s.availBuffer = make([]byte, 0, n)
   938  	}
   939  	return e.s.availBuffer
   940  }
   941  
   942  // StackDepth returns the depth of the state machine for written JSON data.
   943  // Each level on the stack represents a nested JSON object or array.
   944  // It is incremented whenever a [BeginObject] or [BeginArray] token is encountered
   945  // and decremented whenever an [EndObject] or [EndArray] token is encountered.
   946  //
   947  // StackDepth returns 0 when not inside any object or array.
   948  // In particular, it returns 0 before any tokens have been written,
   949  // after any top-level value has been written, and between values
   950  // when encoding a stream of top-level values (e.g., NDJSON).
   951  // StackDepth returns 1 inside a top-level object or array,
   952  // 2 inside a nested object or array, and so on.
   953  //
   954  // For example, consider encoding the following JSON:
   955  //
   956  //	{"a": [1, 2], "b": {"c": 3}}
   957  //
   958  // While encoding, StackDepth would report the following:
   959  //
   960  //   - At the start, StackDepth reports 0.
   961  //   - After encoding the outer '{', StackDepth reports 1.
   962  //   - After encoding the inner '[', StackDepth reports 2.
   963  //   - After encoding the inner ']', StackDepth reports 1.
   964  //   - After encoding the outer '}', StackDepth reports 0.
   965  func (e *Encoder) StackDepth() int {
   966  	// NOTE: Keep in sync with Decoder.StackDepth.
   967  	return e.s.Tokens.Depth() - 1
   968  }
   969  
   970  // StackIndex returns information about the specified stack level.
   971  // It must be a number between 0 and [Encoder.StackDepth], inclusive.
   972  // For each level, it reports the kind:
   973  //
   974  //   - [KindInvalid] for a level of zero,
   975  //   - [KindBeginObject] for a level representing a JSON object, and
   976  //   - [KindBeginArray] for a level representing a JSON array.
   977  //
   978  // It also reports the length of that JSON object or array encoded so far.
   979  // Each name and value in a JSON object is counted separately,
   980  // so the effective number of members is half the length.
   981  // A complete JSON object must have an even length.
   982  func (e *Encoder) StackIndex(i int) (Kind, int64) {
   983  	// NOTE: Keep in sync with Decoder.StackIndex.
   984  	switch s := e.s.Tokens.index(i); {
   985  	case i > 0 && s.isObject():
   986  		return '{', s.Length()
   987  	case i > 0 && s.isArray():
   988  		return '[', s.Length()
   989  	default:
   990  		return 0, s.Length()
   991  	}
   992  }
   993  
   994  // StackPointer returns a JSON Pointer (RFC 6901) to the most recently written value.
   995  func (e *Encoder) StackPointer() Pointer {
   996  	return Pointer(e.s.AppendStackPointer(nil, -1))
   997  }
   998  
   999  func (e *encoderState) AppendStackPointer(b []byte, where int) []byte {
  1000  	e.Names.copyQuotedBuffer(e.Buf)
  1001  	return e.state.appendStackPointer(b, where)
  1002  }
  1003  

View as plain text