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

View as plain text