// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build goexperiment.jsonv2

package jsontext

import (
	
	
	

	
	
	
)

// Encoder is a streaming encoder from raw JSON tokens and values.
// It is used to write a stream of top-level JSON values,
// each terminated with a newline character.
//
// [Encoder.WriteToken] and [Encoder.WriteValue] calls may be interleaved.
// For example, the following JSON value:
//
//	{"name":"value","array":[null,false,true,3.14159],"object":{"k":"v"}}
//
// can be composed with the following calls (ignoring errors for brevity):
//
//	e.WriteToken(BeginObject)        // {
//	e.WriteToken(String("name"))     // "name"
//	e.WriteToken(String("value"))    // "value"
//	e.WriteValue(Value(`"array"`))   // "array"
//	e.WriteToken(BeginArray)         // [
//	e.WriteToken(Null)               // null
//	e.WriteToken(False)              // false
//	e.WriteValue(Value("true"))      // true
//	e.WriteToken(Float(3.14159))     // 3.14159
//	e.WriteToken(EndArray)           // ]
//	e.WriteValue(Value(`"object"`))  // "object"
//	e.WriteValue(Value(`{"k":"v"}`)) // {"k":"v"}
//	e.WriteToken(EndObject)          // }
//
// The above is one of many possible sequence of calls and
// may not represent the most sensible method to call for any given token/value.
// For example, it is probably more common to call [Encoder.WriteToken] with a string
// for object names.
type Encoder struct {
	s encoderState
}

// encoderState is the low-level state of Encoder.
// It has exported fields and method for use by the "json" package.
type encoderState struct {
	state
	encodeBuffer
	jsonopts.Struct

	SeenPointers map[any]struct{} // only used when marshaling; identical to json.seenPointers
}

// encodeBuffer is a buffer split into 2 segments:
//
//   - buf[0:len(buf)]        // written (but unflushed) portion of the buffer
//   - buf[len(buf):cap(buf)] // unused portion of the buffer
type encodeBuffer struct {
	Buf []byte // may alias wr if it is a bytes.Buffer

	// baseOffset is added to len(buf) to obtain the absolute offset
	// relative to the start of io.Writer stream.
	baseOffset int64

	wr io.Writer

	// maxValue is the approximate maximum Value size passed to WriteValue.
	maxValue int
	// unusedCache is the buffer returned by the UnusedBuffer method.
	unusedCache []byte
	// bufStats is statistics about buffer utilization.
	// It is only used with pooled encoders in pools.go.
	bufStats bufferStatistics
}

// NewEncoder constructs a new streaming encoder writing to w
// configured with the provided options.
// It flushes the internal buffer when the buffer is sufficiently full or
// when a top-level value has been written.
//
// If w is a [bytes.Buffer], then the encoder appends directly into the buffer
// without copying the contents from an intermediate buffer.
func ( io.Writer,  ...Options) *Encoder {
	 := new(Encoder)
	.Reset(, ...)
	return 
}

// Reset resets an encoder such that it is writing afresh to w and
// configured with the provided options. Reset must not be called on
// a Encoder passed to the [encoding/json/v2.MarshalerTo.MarshalJSONTo] method
// or the [encoding/json/v2.MarshalToFunc] function.
func ( *Encoder) ( io.Writer,  ...Options) {
	switch {
	case  == nil:
		panic("jsontext: invalid nil Encoder")
	case  == nil:
		panic("jsontext: invalid nil io.Writer")
	case .s.Flags.Get(jsonflags.WithinArshalCall):
		panic("jsontext: cannot reset Encoder passed to json.MarshalerTo")
	}
	.s.reset(nil, , ...)
}

func ( *encoderState) ( []byte,  io.Writer,  ...Options) {
	.state.reset()
	.encodeBuffer = encodeBuffer{Buf: , wr: , bufStats: .bufStats}
	if ,  := .(*bytes.Buffer);  &&  != nil {
		.Buf = .Bytes()[.Len():] // alias the unused buffer of bb
	}
	 := jsonopts.Struct{} // avoid mutating e.Struct in case it is part of opts
	.Join(...)
	.Struct = 
	if .Flags.Get(jsonflags.Multiline) {
		if !.Flags.Has(jsonflags.SpaceAfterColon) {
			.Flags.Set(jsonflags.SpaceAfterColon | 1)
		}
		if !.Flags.Has(jsonflags.SpaceAfterComma) {
			.Flags.Set(jsonflags.SpaceAfterComma | 0)
		}
		if !.Flags.Has(jsonflags.Indent) {
			.Flags.Set(jsonflags.Indent | 1)
			.Indent = "\t"
		}
	}
}

// Options returns the options used to construct the decoder and
// may additionally contain semantic options passed to a
// [encoding/json/v2.MarshalEncode] call.
//
// If operating within
// a [encoding/json/v2.MarshalerTo.MarshalJSONTo] method call or
// a [encoding/json/v2.MarshalToFunc] function call,
// then the returned options are only valid within the call.
func ( *Encoder) () Options {
	return &.s.Struct
}

// NeedFlush determines whether to flush at this point.
func ( *encoderState) () bool {
	// NOTE: This function is carefully written to be inlinable.

	// Avoid flushing if e.wr is nil since there is no underlying writer.
	// Flush if less than 25% of the capacity remains.
	// Flushing at some constant fraction ensures that the buffer stops growing
	// so long as the largest Token or Value fits within that unused capacity.
	return .wr != nil && (.Tokens.Depth() == 1 || len(.Buf) > 3*cap(.Buf)/4)
}

// Flush flushes the buffer to the underlying io.Writer.
// It may append a trailing newline after the top-level value.
func ( *encoderState) () error {
	if .wr == nil || .avoidFlush() {
		return nil
	}

	// In streaming mode, always emit a newline after the top-level value.
	if .Tokens.Depth() == 1 && !.Flags.Get(jsonflags.OmitTopLevelNewline) {
		.Buf = append(.Buf, '\n')
	}

	// Inform objectNameStack that we are about to flush the buffer content.
	.Names.copyQuotedBuffer(.Buf)

	// Specialize bytes.Buffer for better performance.
	if ,  := .wr.(*bytes.Buffer);  {
		// If e.buf already aliases the internal buffer of bb,
		// then the Write call simply increments the internal offset,
		// otherwise Write operates as expected.
		// See https://go.dev/issue/42986.
		,  := .Write(.Buf) // never fails unless bb is nil
		.baseOffset += int64()

		// If the internal buffer of bytes.Buffer is too small,
		// append operations elsewhere in the Encoder may grow the buffer.
		// This would be semantically correct, but hurts performance.
		// As such, ensure 25% of the current length is always available
		// to reduce the probability that other appends must allocate.
		if  := .Available();  < .Len()/4 {
			.Grow( + 1)
		}

		.Buf = .AvailableBuffer()
		return nil
	}

	// Flush the internal buffer to the underlying io.Writer.
	,  := .wr.Write(.Buf)
	.baseOffset += int64()
	if  != nil {
		// In the event of an error, preserve the unflushed portion.
		// Thus, write errors aren't fatal so long as the io.Writer
		// maintains consistent state after errors.
		if  > 0 {
			.Buf = .Buf[:copy(.Buf, .Buf[:])]
		}
		return &ioError{action: "write", err: }
	}
	.Buf = .Buf[:0]

	// Check whether to grow the buffer.
	// Note that cap(e.buf) may already exceed maxBufferSize since
	// an append elsewhere already grew it to store a large token.
	const  = 4 << 10
	const  = 2 // higher value is faster
	const  = 2 // higher value is slower
	// By default, grow if below the maximum buffer size.
	 := cap(.Buf) <= /
	// Growing can be expensive, so only grow
	// if a sufficient number of bytes have been processed.
	 =  && int64(cap(.Buf)) < .previousOffsetEnd()/
	if  {
		.Buf = make([]byte, 0, cap(.Buf)*)
	}

	return nil
}
func ( *encodeBuffer) ( int) int64   { return .baseOffset + int64() }
func ( *encodeBuffer) () int64 { return .baseOffset + int64(len(.Buf)) }
func ( *encodeBuffer) () []byte  { return .Buf }

// avoidFlush indicates whether to avoid flushing to ensure there is always
// enough in the buffer to unwrite the last object member if it were empty.
func ( *encoderState) () bool {
	switch {
	case .Tokens.Last.Length() == 0:
		// Never flush after BeginObject or BeginArray since we don't know yet
		// if the object or array will end up being empty.
		return true
	case .Tokens.Last.needObjectValue():
		// Never flush before the object value since we don't know yet
		// if the object value will end up being empty.
		return true
	case .Tokens.Last.NeedObjectName() && len(.Buf) >= 2:
		// Never flush after the object value if it does turn out to be empty.
		switch string(.Buf[len(.Buf)-2:]) {
		case `ll`, `""`, `{}`, `[]`: // last two bytes of every empty value
			return true
		}
	}
	return false
}

// UnwriteEmptyObjectMember unwrites the last object member if it is empty
// and reports whether it performed an unwrite operation.
func ( *encoderState) ( *string) bool {
	if  := .Tokens.Last; !.isObject() || !.NeedObjectName() || .Length() == 0 {
		panic("BUG: must be called on an object after writing a value")
	}

	// The flushing logic is modified to never flush a trailing empty value.
	// The encoder never writes trailing whitespace eagerly.
	 := .unflushedBuffer()

	// Detect whether the last value was empty.
	var  int
	if len() >= 3 {
		switch string([len()-2:]) {
		case "ll": // last two bytes of `null`
			 = len(`null`)
		case `""`:
			// It is possible for a non-empty string to have `""` as a suffix
			// if the second to the last quote was escaped.
			if [len()-3] == '\\' {
				return false // e.g., `"\""` is not empty
			}
			 = len(`""`)
		case `{}`:
			 = len(`{}`)
		case `[]`:
			 = len(`[]`)
		}
	}
	if  == 0 {
		return false
	}

	// Unwrite the value, whitespace, colon, name, whitespace, and comma.
	 = [:len()-]
	 = jsonwire.TrimSuffixWhitespace()
	 = jsonwire.TrimSuffixByte(, ':')
	 = jsonwire.TrimSuffixString()
	 = jsonwire.TrimSuffixWhitespace()
	 = jsonwire.TrimSuffixByte(, ',')
	.Buf =  // store back truncated unflushed buffer

	// Undo state changes.
	.Tokens.Last.decrement() // for object member value
	.Tokens.Last.decrement() // for object member name
	if !.Flags.Get(jsonflags.AllowDuplicateNames) {
		if .Tokens.Last.isActiveNamespace() {
			.Namespaces.Last().removeLast()
		}
	}
	.Names.clearLast()
	if  != nil {
		.Names.copyQuotedBuffer(.Buf) // required by objectNameStack.replaceLastUnquotedName
		.Names.replaceLastUnquotedName(*)
	}
	return true
}

// UnwriteOnlyObjectMemberName unwrites the only object member name
// and returns the unquoted name.
func ( *encoderState) () string {
	if  := .Tokens.Last; !.isObject() || .Length() != 1 {
		panic("BUG: must be called on an object after writing first name")
	}

	// Unwrite the name and whitespace.
	 := jsonwire.TrimSuffixString(.Buf)
	 := bytes.IndexByte(.Buf[len():], '\\') < 0
	 := string(jsonwire.UnquoteMayCopy(.Buf[len():], ))
	.Buf = jsonwire.TrimSuffixWhitespace()

	// Undo state changes.
	.Tokens.Last.decrement()
	if !.Flags.Get(jsonflags.AllowDuplicateNames) {
		if .Tokens.Last.isActiveNamespace() {
			.Namespaces.Last().removeLast()
		}
	}
	.Names.clearLast()
	return 
}

// WriteToken writes the next token and advances the internal write offset.
//
// The provided token kind must be consistent with the JSON grammar.
// For example, it is an error to provide a number when the encoder
// is expecting an object name (which is always a string), or
// to provide an end object delimiter when the encoder is finishing an array.
// If the provided token is invalid, then it reports a [SyntacticError] and
// the internal state remains unchanged. The offset reported
// in [SyntacticError] will be relative to the [Encoder.OutputOffset].
func ( *Encoder) ( Token) error {
	return .s.WriteToken()
}
func ( *encoderState) ( Token) error {
	 := .Kind()
	 := .Buf // use local variable to avoid mutating e in case of error

	// Append any delimiters or optional whitespace.
	 = .Tokens.MayAppendDelim(, )
	if .Flags.Get(jsonflags.AnyWhitespace) {
		 = .appendWhitespace(, )
	}
	 := len() // offset before the token

	// Append the token to the output and to the state machine.
	var  error
	switch  {
	case 'n':
		 = append(, "null"...)
		 = .Tokens.appendLiteral()
	case 'f':
		 = append(, "false"...)
		 = .Tokens.appendLiteral()
	case 't':
		 = append(, "true"...)
		 = .Tokens.appendLiteral()
	case '"':
		if ,  = .appendString(, &.Flags);  != nil {
			break
		}
		if .Tokens.Last.NeedObjectName() {
			if !.Flags.Get(jsonflags.AllowDuplicateNames) {
				if !.Tokens.Last.isValidNamespace() {
					 = errInvalidNamespace
					break
				}
				if .Tokens.Last.isActiveNamespace() && !.Namespaces.Last().insertQuoted([:], false) {
					 = wrapWithObjectName(ErrDuplicateName, [:])
					break
				}
			}
			.Names.ReplaceLastQuotedOffset() // only replace if insertQuoted succeeds
		}
		 = .Tokens.appendString()
	case '0':
		if ,  = .appendNumber(, &.Flags);  != nil {
			break
		}
		 = .Tokens.appendNumber()
	case '{':
		 = append(, '{')
		if  = .Tokens.pushObject();  != nil {
			break
		}
		.Names.push()
		if !.Flags.Get(jsonflags.AllowDuplicateNames) {
			.Namespaces.push()
		}
	case '}':
		 = append(, '}')
		if  = .Tokens.popObject();  != nil {
			break
		}
		.Names.pop()
		if !.Flags.Get(jsonflags.AllowDuplicateNames) {
			.Namespaces.pop()
		}
	case '[':
		 = append(, '[')
		 = .Tokens.pushArray()
	case ']':
		 = append(, ']')
		 = .Tokens.popArray()
	default:
		 = errInvalidToken
	}
	if  != nil {
		return wrapSyntacticError(, , , +1)
	}

	// Finish off the buffer and store it back into e.
	.Buf = 
	if .NeedFlush() {
		return .Flush()
	}
	return nil
}

// AppendRaw appends either a raw string (without double quotes) or number.
// Specify safeASCII if the string output is guaranteed to be ASCII
// without any characters (including '<', '>', and '&') that need escaping,
// otherwise this will validate whether the string needs escaping.
// The appended bytes for a JSON number must be valid.
//
// This is a specialized implementation of Encoder.WriteValue
// that allows appending directly into the buffer.
// It is only called from marshal logic in the "json" package.
func ( *encoderState) ( Kind,  bool,  func([]byte) ([]byte, error)) error {
	 := .Buf // use local variable to avoid mutating e in case of error

	// Append any delimiters or optional whitespace.
	 = .Tokens.MayAppendDelim(, )
	if .Flags.Get(jsonflags.AnyWhitespace) {
		 = .appendWhitespace(, )
	}
	 := len() // offset before the token

	var  error
	switch  {
	case '"':
		// Append directly into the encoder buffer by assuming that
		// most of the time none of the characters need escaping.
		 = append(, '"')
		if ,  = ();  != nil {
			return 
		}
		 = append(, '"')

		// Check whether we need to escape the string and if necessary
		// copy it to a scratch buffer and then escape it back.
		 :=  || !jsonwire.NeedEscape([+len(`"`):len()-len(`"`)])
		if ! {
			var  error
			 := append(.unusedCache, [+len(`"`):len()-len(`"`)]...)
			,  = jsonwire.AppendQuote([:], string(), &.Flags)
			.unusedCache = [:0]
			if  != nil {
				return wrapSyntacticError(, , , +1)
			}
		}

		// Update the state machine.
		if .Tokens.Last.NeedObjectName() {
			if !.Flags.Get(jsonflags.AllowDuplicateNames) {
				if !.Tokens.Last.isValidNamespace() {
					return wrapSyntacticError(, , , +1)
				}
				if .Tokens.Last.isActiveNamespace() && !.Namespaces.Last().insertQuoted([:], ) {
					 = wrapWithObjectName(ErrDuplicateName, [:])
					return wrapSyntacticError(, , , +1)
				}
			}
			.Names.ReplaceLastQuotedOffset() // only replace if insertQuoted succeeds
		}
		if  := .Tokens.appendString();  != nil {
			return wrapSyntacticError(, , , +1)
		}
	case '0':
		if ,  = ();  != nil {
			return 
		}
		if  := .Tokens.appendNumber();  != nil {
			return wrapSyntacticError(, , , +1)
		}
	default:
		panic("BUG: invalid kind")
	}

	// Finish off the buffer and store it back into e.
	.Buf = 
	if .NeedFlush() {
		return .Flush()
	}
	return nil
}

// WriteValue writes the next raw value and advances the internal write offset.
// The Encoder does not simply copy the provided value verbatim, but
// parses it to ensure that it is syntactically valid and reformats it
// according to how the Encoder is configured to format whitespace and strings.
// If [AllowInvalidUTF8] is specified, then any invalid UTF-8 is mangled
// as the Unicode replacement character, U+FFFD.
//
// The provided value kind must be consistent with the JSON grammar
// (see examples on [Encoder.WriteToken]). If the provided value is invalid,
// then it reports a [SyntacticError] and the internal state remains unchanged.
// The offset reported in [SyntacticError] will be relative to the
// [Encoder.OutputOffset] plus the offset into v of any encountered syntax error.
func ( *Encoder) ( Value) error {
	return .s.WriteValue()
}
func ( *encoderState) ( Value) error {
	.maxValue |= len() // bitwise OR is a fast approximation of max

	 := .Kind()
	 := .Buf // use local variable to avoid mutating e in case of error

	// Append any delimiters or optional whitespace.
	 = .Tokens.MayAppendDelim(, )
	if .Flags.Get(jsonflags.AnyWhitespace) {
		 = .appendWhitespace(, )
	}
	 := len() // offset before the value

	// Append the value the output.
	var  int
	 += jsonwire.ConsumeWhitespace([:])
	, ,  := .reformatValue(, [:], .Tokens.Depth())
	if  != nil {
		return wrapSyntacticError(, , ++, +1)
	}
	 += 
	 += jsonwire.ConsumeWhitespace([:])
	if len() >  {
		 = jsonwire.NewInvalidCharacterError([:], "after top-level value")
		return wrapSyntacticError(, , +, 0)
	}

	// Append the kind to the state machine.
	switch  {
	case 'n', 'f', 't':
		 = .Tokens.appendLiteral()
	case '"':
		if .Tokens.Last.NeedObjectName() {
			if !.Flags.Get(jsonflags.AllowDuplicateNames) {
				if !.Tokens.Last.isValidNamespace() {
					 = errInvalidNamespace
					break
				}
				if .Tokens.Last.isActiveNamespace() && !.Namespaces.Last().insertQuoted([:], false) {
					 = wrapWithObjectName(ErrDuplicateName, [:])
					break
				}
			}
			.Names.ReplaceLastQuotedOffset() // only replace if insertQuoted succeeds
		}
		 = .Tokens.appendString()
	case '0':
		 = .Tokens.appendNumber()
	case '{':
		if  = .Tokens.pushObject();  != nil {
			break
		}
		if  = .Tokens.popObject();  != nil {
			panic("BUG: popObject should never fail immediately after pushObject: " + .Error())
		}
		if .Flags.Get(jsonflags.ReorderRawObjects) {
			mustReorderObjects([:])
		}
	case '[':
		if  = .Tokens.pushArray();  != nil {
			break
		}
		if  = .Tokens.popArray();  != nil {
			panic("BUG: popArray should never fail immediately after pushArray: " + .Error())
		}
		if .Flags.Get(jsonflags.ReorderRawObjects) {
			mustReorderObjects([:])
		}
	}
	if  != nil {
		return wrapSyntacticError(, , , +1)
	}

	// Finish off the buffer and store it back into e.
	.Buf = 
	if .NeedFlush() {
		return .Flush()
	}
	return nil
}

// CountNextDelimWhitespace counts the number of bytes of delimiter and
// whitespace bytes assuming the upcoming token is a JSON value.
// This method is used for error reporting at the semantic layer.
func ( *encoderState) () ( int) {
	const  = Kind('"') // arbitrary kind as next JSON value
	 := .Tokens.needDelim()
	if  > 0 {
		 += len(",") | len(":")
	}
	if  == ':' {
		if .Flags.Get(jsonflags.SpaceAfterColon) {
			 += len(" ")
		}
	} else {
		if  == ',' && .Flags.Get(jsonflags.SpaceAfterComma) {
			 += len(" ")
		}
		if .Flags.Get(jsonflags.Multiline) {
			if  := .Tokens.NeedIndent();  > 0 {
				 += len("\n") + len(.IndentPrefix) + (-1)*len(.Indent)
			}
		}
	}
	return 
}

// appendWhitespace appends whitespace that immediately precedes the next token.
func ( *encoderState) ( []byte,  Kind) []byte {
	if  := .Tokens.needDelim();  == ':' {
		if .Flags.Get(jsonflags.SpaceAfterColon) {
			 = append(, ' ')
		}
	} else {
		if  == ',' && .Flags.Get(jsonflags.SpaceAfterComma) {
			 = append(, ' ')
		}
		if .Flags.Get(jsonflags.Multiline) {
			 = .AppendIndent(, .Tokens.NeedIndent())
		}
	}
	return 
}

// AppendIndent appends the appropriate number of indentation characters
// for the current nested level, n.
func ( *encoderState) ( []byte,  int) []byte {
	if  == 0 {
		return 
	}
	 = append(, '\n')
	 = append(, .IndentPrefix...)
	for ;  > 1; -- {
		 = append(, .Indent...)
	}
	return 
}

// reformatValue parses a JSON value from the start of src and
// appends it to the end of dst, reformatting whitespace and strings as needed.
// It returns the extended dst buffer and the number of consumed input bytes.
func ( *encoderState) ( []byte,  Value,  int) ([]byte, int, error) {
	// TODO: Should this update ValueFlags as input?
	if len() == 0 {
		return , 0, io.ErrUnexpectedEOF
	}
	switch  := Kind([0]).normalize();  {
	case 'n':
		if jsonwire.ConsumeNull() == 0 {
			,  := jsonwire.ConsumeLiteral(, "null")
			return , , 
		}
		return append(, "null"...), len("null"), nil
	case 'f':
		if jsonwire.ConsumeFalse() == 0 {
			,  := jsonwire.ConsumeLiteral(, "false")
			return , , 
		}
		return append(, "false"...), len("false"), nil
	case 't':
		if jsonwire.ConsumeTrue() == 0 {
			,  := jsonwire.ConsumeLiteral(, "true")
			return , , 
		}
		return append(, "true"...), len("true"), nil
	case '"':
		if  := jsonwire.ConsumeSimpleString();  > 0 {
			 = append(, [:]...) // copy simple strings verbatim
			return , , nil
		}
		return jsonwire.ReformatString(, , &.Flags)
	case '0':
		if  := jsonwire.ConsumeSimpleNumber();  > 0 && !.Flags.Get(jsonflags.CanonicalizeNumbers) {
			 = append(, [:]...) // copy simple numbers verbatim
			return , , nil
		}
		return jsonwire.ReformatNumber(, , &.Flags)
	case '{':
		return .reformatObject(, , )
	case '[':
		return .reformatArray(, , )
	default:
		return , 0, jsonwire.NewInvalidCharacterError(, "at start of value")
	}
}

// reformatObject parses a JSON object from the start of src and
// appends it to the end of src, reformatting whitespace and strings as needed.
// It returns the extended dst buffer and the number of consumed input bytes.
func ( *encoderState) ( []byte,  Value,  int) ([]byte, int, error) {
	// Append object start.
	if len() == 0 || [0] != '{' {
		panic("BUG: reformatObject must be called with a buffer that starts with '{'")
	} else if  == maxNestingDepth+1 {
		return , 0, errMaxDepth
	}
	 = append(, '{')
	 := len("{")

	// Append (possible) object end.
	 += jsonwire.ConsumeWhitespace([:])
	if uint(len()) <= uint() {
		return , , io.ErrUnexpectedEOF
	}
	if [] == '}' {
		 = append(, '}')
		 += len("}")
		return , , nil
	}

	var  error
	var  *objectNamespace
	if !.Flags.Get(jsonflags.AllowDuplicateNames) {
		.Namespaces.push()
		defer .Namespaces.pop()
		 = .Namespaces.Last()
	}
	++
	for {
		// Append optional newline and indentation.
		if .Flags.Get(jsonflags.Multiline) {
			 = .AppendIndent(, )
		}

		// Append object name.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , io.ErrUnexpectedEOF
		}
		 := jsonwire.ConsumeSimpleString([:])
		 :=  > 0
		if  {
			 = append(, [:+]...)
		} else {
			, ,  = jsonwire.ReformatString(, [:], &.Flags)
			if  != nil {
				return ,  + , 
			}
		}
		 := [ : +]
		if !.Flags.Get(jsonflags.AllowDuplicateNames) && !.insertQuoted(, ) {
			return , , wrapWithObjectName(ErrDuplicateName, )
		}
		 += 

		// Append colon.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , wrapWithObjectName(io.ErrUnexpectedEOF, )
		}
		if [] != ':' {
			 = jsonwire.NewInvalidCharacterError([:], "after object name (expecting ':')")
			return , , wrapWithObjectName(, )
		}
		 = append(, ':')
		 += len(":")
		if .Flags.Get(jsonflags.SpaceAfterColon) {
			 = append(, ' ')
		}

		// Append object value.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , wrapWithObjectName(io.ErrUnexpectedEOF, )
		}
		, ,  = .reformatValue(, [:], )
		if  != nil {
			return ,  + , wrapWithObjectName(, )
		}
		 += 

		// Append comma or object end.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , io.ErrUnexpectedEOF
		}
		switch [] {
		case ',':
			 = append(, ',')
			if .Flags.Get(jsonflags.SpaceAfterComma) {
				 = append(, ' ')
			}
			 += len(",")
			continue
		case '}':
			if .Flags.Get(jsonflags.Multiline) {
				 = .AppendIndent(, -1)
			}
			 = append(, '}')
			 += len("}")
			return , , nil
		default:
			return , , jsonwire.NewInvalidCharacterError([:], "after object value (expecting ',' or '}')")
		}
	}
}

// reformatArray parses a JSON array from the start of src and
// appends it to the end of dst, reformatting whitespace and strings as needed.
// It returns the extended dst buffer and the number of consumed input bytes.
func ( *encoderState) ( []byte,  Value,  int) ([]byte, int, error) {
	// Append array start.
	if len() == 0 || [0] != '[' {
		panic("BUG: reformatArray must be called with a buffer that starts with '['")
	} else if  == maxNestingDepth+1 {
		return , 0, errMaxDepth
	}
	 = append(, '[')
	 := len("[")

	// Append (possible) array end.
	 += jsonwire.ConsumeWhitespace([:])
	if uint(len()) <= uint() {
		return , , io.ErrUnexpectedEOF
	}
	if [] == ']' {
		 = append(, ']')
		 += len("]")
		return , , nil
	}

	var  int64
	var  error
	++
	for {
		// Append optional newline and indentation.
		if .Flags.Get(jsonflags.Multiline) {
			 = .AppendIndent(, )
		}

		// Append array value.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , io.ErrUnexpectedEOF
		}
		var  int
		, ,  = .reformatValue(, [:], )
		if  != nil {
			return ,  + , wrapWithArrayIndex(, )
		}
		 += 

		// Append comma or array end.
		 += jsonwire.ConsumeWhitespace([:])
		if uint(len()) <= uint() {
			return , , io.ErrUnexpectedEOF
		}
		switch [] {
		case ',':
			 = append(, ',')
			if .Flags.Get(jsonflags.SpaceAfterComma) {
				 = append(, ' ')
			}
			 += len(",")
			++
			continue
		case ']':
			if .Flags.Get(jsonflags.Multiline) {
				 = .AppendIndent(, -1)
			}
			 = append(, ']')
			 += len("]")
			return , , nil
		default:
			return , , jsonwire.NewInvalidCharacterError([:], "after array value (expecting ',' or ']')")
		}
	}
}

// OutputOffset returns the current output byte offset. It gives the location
// of the next byte immediately after the most recently written token or value.
// The number of bytes actually written to the underlying [io.Writer] may be less
// than this offset due to internal buffering effects.
func ( *Encoder) () int64 {
	return .s.previousOffsetEnd()
}

// UnusedBuffer returns a zero-length buffer with a possible non-zero capacity.
// This buffer is intended to be used to populate a [Value]
// being passed to an immediately succeeding [Encoder.WriteValue] call.
//
// Example usage:
//
//	b := d.UnusedBuffer()
//	b = append(b, '"')
//	b = appendString(b, v) // append the string formatting of v
//	b = append(b, '"')
//	... := d.WriteValue(b)
//
// It is the user's responsibility to ensure that the value is valid JSON.
func ( *Encoder) () []byte {
	// NOTE: We don't return e.buf[len(e.buf):cap(e.buf)] since WriteValue would
	// need to take special care to avoid mangling the data while reformatting.
	// WriteValue can't easily identify whether the input Value aliases e.buf
	// without using unsafe.Pointer. Thus, we just return a different buffer.
	// Should this ever alias e.buf, we need to consider how it operates with
	// the specialized performance optimization for bytes.Buffer.
	 := 1 << bits.Len(uint(.s.maxValue|63)) // fast approximation for max length
	if cap(.s.unusedCache) <  {
		.s.unusedCache = make([]byte, 0, )
	}
	return .s.unusedCache
}

// StackDepth returns the depth of the state machine for written JSON data.
// Each level on the stack represents a nested JSON object or array.
// It is incremented whenever an [BeginObject] or [BeginArray] token is encountered
// and decremented whenever an [EndObject] or [EndArray] token is encountered.
// The depth is zero-indexed, where zero represents the top-level JSON value.
func ( *Encoder) () int {
	// NOTE: Keep in sync with Decoder.StackDepth.
	return .s.Tokens.Depth() - 1
}

// StackIndex returns information about the specified stack level.
// It must be a number between 0 and [Encoder.StackDepth], inclusive.
// For each level, it reports the kind:
//
//   - 0 for a level of zero,
//   - '{' for a level representing a JSON object, and
//   - '[' for a level representing a JSON array.
//
// It also reports the length of that JSON object or array.
// Each name and value in a JSON object is counted separately,
// so the effective number of members would be half the length.
// A complete JSON object must have an even length.
func ( *Encoder) ( int) (Kind, int64) {
	// NOTE: Keep in sync with Decoder.StackIndex.
	switch  := .s.Tokens.index(); {
	case  > 0 && .isObject():
		return '{', .Length()
	case  > 0 && .isArray():
		return '[', .Length()
	default:
		return 0, .Length()
	}
}

// StackPointer returns a JSON Pointer (RFC 6901) to the most recently written value.
func ( *Encoder) () Pointer {
	return Pointer(.s.AppendStackPointer(nil, -1))
}

func ( *encoderState) ( []byte,  int) []byte {
	.Names.copyQuotedBuffer(.Buf)
	return .state.appendStackPointer(, )
}