// 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.jsonv2package jsontextimport ()// NOTE: The logic for decoding is complicated by the fact that reading from// an io.Reader into a temporary buffer means that the buffer may contain a// truncated portion of some valid input, requiring the need to fetch more data.//// This file is structured in the following way://// - consumeXXX functions parse an exact JSON token from a []byte.// If the buffer appears truncated, then it returns io.ErrUnexpectedEOF.// The consumeSimpleXXX functions are so named because they only handle// a subset of the grammar for the JSON token being parsed.// They do not handle the full grammar to keep these functions inlinable.//// - Decoder.consumeXXX methods parse the next JSON token from Decoder.buf,// automatically fetching more input if necessary. These methods take// a position relative to the start of Decoder.buf as an argument and// return the end of the consumed JSON token as a position,// also relative to the start of Decoder.buf.//// - In the event of an I/O error or state machine violations,// the implementation avoids mutating the state of Decoder// (aside from the book-keeping needed to implement Decoder.fetch).// For this reason, only Decoder.ReadToken and Decoder.ReadValue are// responsible for updating Decoder.prevStart and Decoder.prevEnd.//// - For performance, much of the implementation uses the pattern of calling// the inlinable consumeXXX functions first, and if more work is necessary,// then it calls the slower Decoder.consumeXXX methods.// TODO: Revisit this pattern if the Go compiler provides finer control// over exactly which calls are inlined or not.// Decoder is a streaming decoder for raw JSON tokens and values.// It is used to read a stream of top-level JSON values,// each separated by optional whitespace characters.//// [Decoder.ReadToken] and [Decoder.ReadValue] calls may be interleaved.// For example, the following JSON value://// {"name":"value","array":[null,false,true,3.14159],"object":{"k":"v"}}//// can be parsed with the following calls (ignoring errors for brevity)://// d.ReadToken() // {// d.ReadToken() // "name"// d.ReadToken() // "value"// d.ReadValue() // "array"// d.ReadToken() // [// d.ReadToken() // null// d.ReadToken() // false// d.ReadValue() // true// d.ReadToken() // 3.14159// d.ReadToken() // ]// d.ReadValue() // "object"// d.ReadValue() // {"k":"v"}// d.ReadToken() // }//// The above is one of many possible sequences 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 [Decoder.ReadToken] to obtain a// string token for object names.typeDecoderstruct {sdecoderState}// decoderState is the low-level state of Decoder.// It has exported fields and methods for use by the "json" package.typedecoderStatestruct {statedecodeBufferjsonopts.StructStringCache *[256]string// only used when unmarshaling; identical to json.stringCache}// decodeBuffer is a buffer split into 4 segments://// - buf[0:prevEnd] // already read portion of the buffer// - buf[prevStart:prevEnd] // previously read value// - buf[prevEnd:len(buf)] // unread portion of the buffer// - buf[len(buf):cap(buf)] // unused portion of the buffer//// Invariants://// 0 ≤ prevStart ≤ prevEnd ≤ len(buf) ≤ cap(buf)typedecodeBufferstruct {peekPosint// non-zero if valid offset into buf for start of next tokenpeekErrerror// implies peekPos is -1buf []byte// may alias rd if it is a bytes.BufferprevStartintprevEndint// baseOffset is added to prevStart and prevEnd to obtain // the absolute offset relative to the start of io.Reader stream.baseOffsetint64rdio.Reader}// NewDecoder constructs a new streaming decoder reading from r.//// If r is a [bytes.Buffer], then the decoder parses directly from the buffer// without first copying the contents to an intermediate buffer.// Additional writes to the buffer must not occur while the decoder is in use.func ( io.Reader, ...Options) *Decoder { := new(Decoder) .Reset(, ...)return}// Reset resets a decoder such that it is reading afresh from r and// configured with the provided options. Reset must not be called on// a Decoder passed to the [encoding/json/v2.UnmarshalerFrom.UnmarshalJSONFrom] method// or the [encoding/json/v2.UnmarshalFromFunc] function.func ( *Decoder) ( io.Reader, ...Options) {switch {case == nil:panic("jsontext: invalid nil Decoder")case == nil:panic("jsontext: invalid nil io.Reader")case .s.Flags.Get(jsonflags.WithinArshalCall):panic("jsontext: cannot reset Decoder passed to json.UnmarshalerFrom") }// Reuse the buffer if it does not alias a previous [bytes.Buffer]. := .s.buf[:0]if , := .s.rd.(*bytes.Buffer); { = nil } .s.reset(, , ...)}func ( *decoderState) ( []byte, io.Reader, ...Options) { .state.reset() .decodeBuffer = decodeBuffer{buf: , rd: } := jsonopts.Struct{} // avoid mutating d.Struct in case it is part of opts .Join(...) .Struct = }// Options returns the options used to construct the decoder and// may additionally contain semantic options passed to a// [encoding/json/v2.UnmarshalDecode] call.//// If operating within// a [encoding/json/v2.UnmarshalerFrom.UnmarshalJSONFrom] method call or// a [encoding/json/v2.UnmarshalFromFunc] function call,// then the returned options are only valid within the call.func ( *Decoder) () Options {return &.s.Struct}func ( *decoderState) () *jsonopts.Struct { return &.Struct }varerrBufferWriteAfterNext = errors.New("invalid bytes.Buffer.Write call after calling bytes.Buffer.Next")// fetch reads at least 1 byte from the underlying io.Reader.// It returns io.ErrUnexpectedEOF if zero bytes were read and io.EOF was seen.func ( *decoderState) () error {if .rd == nil {returnio.ErrUnexpectedEOF }// Inform objectNameStack that we are about to fetch new buffer content. .Names.copyQuotedBuffer(.buf)// Specialize bytes.Buffer for better performance.if , := .rd.(*bytes.Buffer); {switch {case .Len() == 0:returnio.ErrUnexpectedEOFcaselen(.buf) == 0: .buf = .Next(.Len()) // "read" all data in the bufferreturnnildefault:// This only occurs if a partially filled bytes.Buffer was provided // and more data is written to it while Decoder is reading from it. // This practice will lead to data corruption since future writes // may overwrite the contents of the current buffer. // // The user is trying to use a bytes.Buffer as a pipe, // but a bytes.Buffer is a poor implementation of a pipe, // the purpose-built io.Pipe should be used instead.return &ioError{action: "read", err: errBufferWriteAfterNext} } }// Allocate initial buffer if empty.ifcap(.buf) == 0 { .buf = make([]byte, 0, 64) }// Check whether to grow the buffer.const = 4 << 10const = 2// higher value is fasterconst = 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 prevStart==0, then fetch was called in order to fetch more data // to finish consuming a large JSON value contiguously. // Grow if less than 25% of the remaining capacity is available. // Note that this may cause the input buffer to exceed maxBufferSize. = || (.prevStart == 0 && len(.buf) >= 3*cap(.buf)/4)if {// Allocate a new buffer and copy the contents of the old buffer over. // TODO: Provide a hard limit on the maximum internal buffer size? := make([]byte, 0, cap(.buf)*) .buf = append(, .buf[.prevStart:]...) } else {// Move unread portion of the data to the front. := copy(.buf[:cap(.buf)], .buf[.prevStart:]) .buf = .buf[:] } .baseOffset += int64(.prevStart) .prevEnd -= .prevStart .prevStart = 0// Read more data into the internal buffer.for { , := .rd.Read(.buf[len(.buf):cap(.buf)])switch {case > 0: .buf = .buf[:len(.buf)+]returnnil// ignore errors if any bytes are readcase == io.EOF:returnio.ErrUnexpectedEOFcase != nil:return &ioError{action: "read", err: }default:continue// Read returned (0, nil) } }}constinvalidateBufferByte = '#'// invalid starting character for JSON grammar// invalidatePreviousRead invalidates buffers returned by Peek and Read calls// so that the first byte is an invalid character.// This Hyrum-proofs the API against faulty application code that assumes// values returned by ReadValue remain valid past subsequent Read calls.func ( *decodeBuffer) () {// Avoid mutating the buffer if d.rd is nil which implies that d.buf // is provided by the user code and may not expect mutations. := func( io.Reader) bool { , := .(*bytes.Buffer)return }if .rd != nil && !(.rd) && .prevStart < .prevEnd && uint(.prevStart) < uint(len(.buf)) { .buf[.prevStart] = invalidateBufferByte .prevStart = .prevEnd }}// needMore reports whether there are no more unread bytes.func ( *decodeBuffer) ( int) bool {// NOTE: The arguments and logic are kept simple to keep this inlinable.return == len(.buf)}func ( *decodeBuffer) ( int) int64 { return .baseOffset + int64() }func ( *decodeBuffer) () int64 { return .baseOffset + int64(.prevStart) }func ( *decodeBuffer) () int64 { return .baseOffset + int64(.prevEnd) }func ( *decodeBuffer) () []byte { return .buf[.prevStart:.prevEnd] }func ( *decodeBuffer) () []byte { return .buf[.prevEnd:len(.buf)] }// PreviousTokenOrValue returns the previously read token or value// unless it has been invalidated by a call to PeekKind.// If a token is just a delimiter, then this returns a 1-byte buffer.// This method is used for error reporting at the semantic layer.func ( *decodeBuffer) () []byte { := .previousBuffer()// If peek was called, then the previous token or buffer is invalidated.if .peekPos > 0 || len() > 0 && [0] == invalidateBufferByte {returnnil }// ReadToken does not preserve the buffer for null, bools, or delimiters. // Manually re-construct that buffer.iflen() == 0 { = .buf[:.prevEnd] // entirety of the previous bufferfor , := range []string{"null", "false", "true", "{", "}", "[", "]"} {iflen() >= len() && string([len()-len():]) == {return [len()-len():] } } }return}// PeekKind retrieves the next token kind, but does not advance the read offset.//// It returns [KindInvalid] if an error occurs. Any such error is cached until// the next read call and it is the caller's responsibility to eventually// follow up a PeekKind call with a read call.func ( *Decoder) () Kind {return .s.PeekKind()}func ( *decoderState) () Kind {// Check whether we have a cached peek result.if .peekPos > 0 {returnKind(.buf[.peekPos]).normalize() }varerror .invalidatePreviousRead() := .prevEnd// Consume leading whitespace. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {if == io.ErrUnexpectedEOF && .Tokens.Depth() == 1 { = io.EOF// EOF possibly if no Tokens present after top-level value } .peekPos, .peekErr = -1, wrapSyntacticError(, , , 0)returninvalidKind } }// Consume colon or comma.varbyteif := .buf[]; == ':' || == ',' { = += 1 += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil { = wrapSyntacticError(, , , 0) .peekPos, .peekErr = -1, .checkDelimBeforeIOError(, )returninvalidKind } } } := Kind(.buf[]).normalize()if .Tokens.needDelim() != { .peekPos, .peekErr = -1, .checkDelim(, )returninvalidKind }// This may set peekPos to zero, which is indistinguishable from // the uninitialized state. While a small hit to performance, it is correct // since ReadValue and ReadToken will disregard the cached result and // recompute the next kind. .peekPos, .peekErr = , nilreturn}// checkDelimBeforeIOError checks whether the delim is even valid// before returning an IO error, which occurs after the delim.func ( *decoderState) ( byte, error) error {// Since an IO error occurred, we do not know what the next kind is. // However, knowing the next kind is necessary to validate // whether the current delim is at least potentially valid. // Since a JSON string is always valid as the next token, // conservatively assume that is the next kind for validation.const = Kind('"')if .Tokens.needDelim() != { = .checkDelim(, ) }return}// CountNextDelimWhitespace counts the number of upcoming bytes of// delimiter or whitespace characters.// This method is used for error reporting at the semantic layer.func ( *decoderState) () int { .PeekKind() // populate unreadBufferreturnlen(.unreadBuffer()) - len(bytes.TrimLeft(.unreadBuffer(), ",: \n\r\t"))}// checkDelim checks whether delim is valid for the given next kind.func ( *decoderState) ( byte, Kind) error { := "at start of value"switch .Tokens.needDelim() {case :returnnilcase':': = "after object name (expecting ':')"case',':if .Tokens.Last.isObject() { = "after object value (expecting ',' or '}')" } else { = "after array element (expecting ',' or ']')" } } := .prevEnd// restore position to right after leading whitespace += jsonwire.ConsumeWhitespace(.buf[:]) := jsonwire.NewInvalidCharacterError(.buf[:], )returnwrapSyntacticError(, , , 0)}// SkipValue is semantically equivalent to calling [Decoder.ReadValue] and discarding// the result, except that memory is not wasted trying to hold the entire result.func ( *Decoder) () error {return .s.SkipValue()}func ( *decoderState) () error {switch .PeekKind() {case'{', '[':// For JSON objects and arrays, keep skipping all tokens // until the depth matches the starting depth. := .Tokens.Depth()for {if , := .ReadToken(); != nil {return }if >= .Tokens.Depth() {returnnil } }default:// Trying to skip a value when the next token is a '}' or ']' // will result in an error being returned here.varjsonwire.ValueFlagsif , := .ReadValue(&); != nil {return }returnnil }}// SkipValueRemainder skips the remainder of a value// after reading a '{' or '[' token.func ( *decoderState) () error {if .Tokens.Depth()-1 > 0 && .Tokens.Last.Length() == 0 {for := .Tokens.Depth(); .Tokens.Depth() >= ; {if , := .ReadToken(); != nil {return } } }returnnil}// SkipUntil skips all tokens until the state machine// is at or past the specified depth and length.func ( *decoderState) ( int, int64) error {for .Tokens.Depth() > || (.Tokens.Depth() == && .Tokens.Last.Length() < ) {if , := .ReadToken(); != nil {return } }returnnil}// ReadToken reads the next [Token], advancing the read offset.// The returned token is only valid until the next Peek, Read, or Skip call.// It returns [io.EOF] if there are no more tokens.func ( *Decoder) () (Token, error) {return .s.ReadToken()}func ( *decoderState) () (Token, error) {// Determine the next kind.varerrorvarKind := .peekPosif != 0 {// Use cached peek result.if .peekErr != nil { := .peekErr .peekPos, .peekErr = 0, nil// possibly a transient I/O errorreturnToken{}, } = Kind(.buf[]).normalize() .peekPos = 0// reset cache } else { .invalidatePreviousRead() = .prevEnd// Consume leading whitespace. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {if == io.ErrUnexpectedEOF && .Tokens.Depth() == 1 { = io.EOF// EOF possibly if no Tokens present after top-level value }returnToken{}, wrapSyntacticError(, , , 0) } }// Consume colon or comma.varbyteif := .buf[]; == ':' || == ',' { = += 1 += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil { = wrapSyntacticError(, , , 0)returnToken{}, .checkDelimBeforeIOError(, ) } } } = Kind(.buf[]).normalize()if .Tokens.needDelim() != {returnToken{}, .checkDelim(, ) } }// Handle the next token.varintswitch {case'n':ifjsonwire.ConsumeNull(.buf[:]) == 0 { , = .consumeLiteral(, "null")if != nil {returnToken{}, wrapSyntacticError(, , , +1) } } else { += len("null") }if = .Tokens.appendLiteral(); != nil {returnToken{}, wrapSyntacticError(, , -len("null"), +1) // report position at start of literal } .prevStart, .prevEnd = , returnNull, nilcase'f':ifjsonwire.ConsumeFalse(.buf[:]) == 0 { , = .consumeLiteral(, "false")if != nil {returnToken{}, wrapSyntacticError(, , , +1) } } else { += len("false") }if = .Tokens.appendLiteral(); != nil {returnToken{}, wrapSyntacticError(, , -len("false"), +1) // report position at start of literal } .prevStart, .prevEnd = , returnFalse, nilcase't':ifjsonwire.ConsumeTrue(.buf[:]) == 0 { , = .consumeLiteral(, "true")if != nil {returnToken{}, wrapSyntacticError(, , , +1) } } else { += len("true") }if = .Tokens.appendLiteral(); != nil {returnToken{}, wrapSyntacticError(, , -len("true"), +1) // report position at start of literal } .prevStart, .prevEnd = , returnTrue, nilcase'"':varjsonwire.ValueFlags// TODO: Preserve this in Token?if = jsonwire.ConsumeSimpleString(.buf[:]); == 0 { := .baseOffset + int64() , = .consumeString(&, ) := .baseOffset + int64() = int( - )if != nil {returnToken{}, wrapSyntacticError(, , , +1) } } else { += }if .Tokens.Last.NeedObjectName() {if !.Flags.Get(jsonflags.AllowDuplicateNames) {if !.Tokens.Last.isValidNamespace() {returnToken{}, wrapSyntacticError(, errInvalidNamespace, -, +1) }if .Tokens.Last.isActiveNamespace() && !.Namespaces.Last().insertQuoted(.buf[-:], .IsVerbatim()) { = wrapWithObjectName(ErrDuplicateName, .buf[-:])returnToken{}, wrapSyntacticError(, , -, +1) // report position at start of string } } .Names.ReplaceLastQuotedOffset( - ) // only replace if insertQuoted succeeds }if = .Tokens.appendString(); != nil {returnToken{}, wrapSyntacticError(, , -, +1) // report position at start of string } .prevStart, .prevEnd = -, returnToken{raw: &.decodeBuffer, num: uint64(.previousOffsetStart())}, nilcase'0':// NOTE: Since JSON numbers are not self-terminating, // we need to make sure that the next byte is not part of a number.if = jsonwire.ConsumeSimpleNumber(.buf[:]); == 0 || .needMore(+) { := .baseOffset + int64() , = .consumeNumber() := .baseOffset + int64() = int( - )if != nil {returnToken{}, wrapSyntacticError(, , , +1) } } else { += }if = .Tokens.appendNumber(); != nil {returnToken{}, wrapSyntacticError(, , -, +1) // report position at start of number } .prevStart, .prevEnd = -, returnToken{raw: &.decodeBuffer, num: uint64(.previousOffsetStart())}, nilcase'{':if = .Tokens.pushObject(); != nil {returnToken{}, wrapSyntacticError(, , , +1) } .Names.push()if !.Flags.Get(jsonflags.AllowDuplicateNames) { .Namespaces.push() } .Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth += 1 .prevStart, .prevEnd = , returnBeginObject, nilcase'}':if = .Tokens.popObject(); != nil {returnToken{}, wrapSyntacticError(, , , +1) } .Names.pop()if !.Flags.Get(jsonflags.AllowDuplicateNames) { .Namespaces.pop() } += 1 .prevStart, .prevEnd = , returnEndObject, nilcase'[':if = .Tokens.pushArray(); != nil {returnToken{}, wrapSyntacticError(, , , +1) } .Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth += 1 .prevStart, .prevEnd = , returnBeginArray, nilcase']':if = .Tokens.popArray(); != nil {returnToken{}, wrapSyntacticError(, , , +1) } += 1 .prevStart, .prevEnd = , returnEndArray, nildefault: = jsonwire.NewInvalidCharacterError(.buf[:], "at start of value")returnToken{}, wrapSyntacticError(, , , +1) }}// ReadValue returns the next raw JSON value, advancing the read offset.// The value is stripped of any leading or trailing whitespace and// contains the exact bytes of the input, which may contain invalid UTF-8// if [AllowInvalidUTF8] is specified.//// The returned value is only valid until the next Peek, Read, or Skip call and// may not be mutated while the Decoder remains in use.// If the decoder is currently at the end token for an object or array,// then it reports a [SyntacticError] and the internal state remains unchanged.// It returns [io.EOF] if there are no more values.func ( *Decoder) () (Value, error) {varjsonwire.ValueFlagsreturn .s.ReadValue(&)}func ( *decoderState) ( *jsonwire.ValueFlags) (Value, error) {// Determine the next kind.varerrorvarKind := .peekPosif != 0 {// Use cached peek result.if .peekErr != nil { := .peekErr .peekPos, .peekErr = 0, nil// possibly a transient I/O errorreturnnil, } = Kind(.buf[]).normalize() .peekPos = 0// reset cache } else { .invalidatePreviousRead() = .prevEnd// Consume leading whitespace. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {if == io.ErrUnexpectedEOF && .Tokens.Depth() == 1 { = io.EOF// EOF possibly if no Tokens present after top-level value }returnnil, wrapSyntacticError(, , , 0) } }// Consume colon or comma.varbyteif := .buf[]; == ':' || == ',' { = += 1 += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil { = wrapSyntacticError(, , , 0)returnnil, .checkDelimBeforeIOError(, ) } } } = Kind(.buf[]).normalize()if .Tokens.needDelim() != {returnnil, .checkDelim(, ) } }// Handle the next value. := .baseOffset + int64() , = .consumeValue(, , .Tokens.Depth()) := .baseOffset + int64() := int( - )if != nil {returnnil, wrapSyntacticError(, , , +1) }switch {case'n', 't', 'f': = .Tokens.appendLiteral()case'"':if .Tokens.Last.NeedObjectName() {if !.Flags.Get(jsonflags.AllowDuplicateNames) {if !.Tokens.Last.isValidNamespace() { = errInvalidNamespacebreak }if .Tokens.Last.isActiveNamespace() && !.Namespaces.Last().insertQuoted(.buf[-:], .IsVerbatim()) { = wrapWithObjectName(ErrDuplicateName, .buf[-:])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()) }case'[':if = .Tokens.pushArray(); != nil {break }if = .Tokens.popArray(); != nil {panic("BUG: popArray should never fail immediately after pushArray: " + .Error()) } }if != nil {returnnil, wrapSyntacticError(, , -, +1) // report position at start of value } .prevEnd = .prevStart = - return .buf[- : : ], nil}// CheckNextValue checks whether the next value is syntactically valid,// but does not advance the read offset.// If last, it verifies that the stream cleanly terminates with [io.EOF].func ( *decoderState) ( bool) error { .PeekKind() // populates d.peekPos and d.peekErr , := .peekPos, .peekErr .peekPos, .peekErr = 0, nilif != nil {return }varjsonwire.ValueFlagsif , := .consumeValue(&, , .Tokens.Depth()); != nil {returnwrapSyntacticError(, , , +1) } elseif {return .checkEOF() }returnnil}// AtEOF reports whether the decoder is at EOF.func ( *decoderState) () bool { , := .consumeWhitespace(.prevEnd)return == io.ErrUnexpectedEOF}// CheckEOF verifies that the input has no more data.func ( *decoderState) () error {return .checkEOF(.prevEnd)}func ( *decoderState) ( int) error {switch , := .consumeWhitespace(); {casenil: := jsonwire.NewInvalidCharacterError(.buf[:], "after top-level value")returnwrapSyntacticError(, , , 0)caseio.ErrUnexpectedEOF:returnnildefault:return }}// consumeWhitespace consumes all whitespace starting at d.buf[pos:].// It returns the new position in d.buf immediately after the last whitespace.// If it returns nil, there is guaranteed to at least be one unread byte.//// The following pattern is common in this implementation://// pos += jsonwire.ConsumeWhitespace(d.buf[pos:])// if d.needMore(pos) {// if pos, err = d.consumeWhitespace(pos); err != nil {// return ...// }// }//// It is difficult to simplify this without sacrificing performance since// consumeWhitespace must be inlined. The body of the if statement is// executed only in rare situations where we need to fetch more data.// Since fetching may return an error, we also need to check the error.func ( *decoderState) ( int) ( int, error) {for { += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() { := .baseOffset + int64() = .fetch() // will mutate d.buf and invalidate pos = int( - .baseOffset)if != nil {return , }continue }return , nil }}// consumeValue consumes a single JSON value starting at d.buf[pos:].// It returns the new position in d.buf immediately after the value.func ( *decoderState) ( *jsonwire.ValueFlags, , int) ( int, error) {for {varintvarerrorswitch := Kind(.buf[]).normalize(); {case'n':if = jsonwire.ConsumeNull(.buf[:]); == 0 { , = jsonwire.ConsumeLiteral(.buf[:], "null") }case'f':if = jsonwire.ConsumeFalse(.buf[:]); == 0 { , = jsonwire.ConsumeLiteral(.buf[:], "false") }case't':if = jsonwire.ConsumeTrue(.buf[:]); == 0 { , = jsonwire.ConsumeLiteral(.buf[:], "true") }case'"':if = jsonwire.ConsumeSimpleString(.buf[:]); == 0 {return .consumeString(, ) }case'0':// NOTE: Since JSON numbers are not self-terminating, // we need to make sure that the next byte is not part of a number.if = jsonwire.ConsumeSimpleNumber(.buf[:]); == 0 || .needMore(+) {return .consumeNumber() }case'{':return .consumeObject(, , )case'[':return .consumeArray(, , )default:if (.Tokens.Last.isObject() && == ']') || (.Tokens.Last.isArray() && == '}') {return , errMismatchDelim }return , jsonwire.NewInvalidCharacterError(.buf[:], "at start of value") }if == io.ErrUnexpectedEOF { := .baseOffset + int64() = .fetch() // will mutate d.buf and invalidate pos = int( - .baseOffset)if != nil {return + , }continue }return + , }}// consumeLiteral consumes a single JSON literal starting at d.buf[pos:].// It returns the new position in d.buf immediately after the literal.func ( *decoderState) ( int, string) ( int, error) {for { , := jsonwire.ConsumeLiteral(.buf[:], )if == io.ErrUnexpectedEOF { := .baseOffset + int64() = .fetch() // will mutate d.buf and invalidate pos = int( - .baseOffset)if != nil {return + , }continue }return + , }}// consumeString consumes a single JSON string starting at d.buf[pos:].// It returns the new position in d.buf immediately after the string.func ( *decoderState) ( *jsonwire.ValueFlags, int) ( int, error) {varintfor { , = jsonwire.ConsumeStringResumable(, .buf[:], , !.Flags.Get(jsonflags.AllowInvalidUTF8))if == io.ErrUnexpectedEOF { := .baseOffset + int64() = .fetch() // will mutate d.buf and invalidate pos = int( - .baseOffset)if != nil {return + , }continue }return + , }}// consumeNumber consumes a single JSON number starting at d.buf[pos:].// It returns the new position in d.buf immediately after the number.func ( *decoderState) ( int) ( int, error) {varintvarjsonwire.ConsumeNumberStatefor { , , = jsonwire.ConsumeNumberResumable(.buf[:], , )// NOTE: Since JSON numbers are not self-terminating, // we need to make sure that the next byte is not part of a number.if == io.ErrUnexpectedEOF || .needMore(+) { := == nil := .baseOffset + int64() = .fetch() // will mutate d.buf and invalidate pos = int( - .baseOffset)if != nil {if && == io.ErrUnexpectedEOF {return + , nil }return , }continue }return + , }}// consumeObject consumes a single JSON object starting at d.buf[pos:].// It returns the new position in d.buf immediately after the object.func ( *decoderState) ( *jsonwire.ValueFlags, , int) ( int, error) {varintvar *objectNamespaceif !.Flags.Get(jsonflags.AllowDuplicateNames) { .Namespaces.push()defer .Namespaces.pop() = .Namespaces.Last() }// Handle before start.ifuint() >= uint(len(.buf)) || .buf[] != '{' {panic("BUG: consumeObject must be called with a buffer that starts with '{'") } elseif == maxNestingDepth+1 {return , errMaxDepth } ++// Handle after start. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } }if .buf[] == '}' { ++return , nil } ++for {// Handle before name. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } }varjsonwire.ValueFlagsif = jsonwire.ConsumeSimpleString(.buf[:]); == 0 { := .baseOffset + int64() , = .consumeString(&, ) := .baseOffset + int64() = int( - ) .Join()if != nil {return , } } else { += } := .buf[- : ]if !.Flags.Get(jsonflags.AllowDuplicateNames) && !.insertQuoted(, .IsVerbatim()) {return - , wrapWithObjectName(ErrDuplicateName, ) }// Handle after name. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , wrapWithObjectName(, ) } }if .buf[] != ':' { := jsonwire.NewInvalidCharacterError(.buf[:], "after object name (expecting ':')")return , wrapWithObjectName(, ) } ++// Handle before value. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , wrapWithObjectName(, ) } } , = .consumeValue(, , )if != nil {return , wrapWithObjectName(, ) }// Handle after value. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } }switch .buf[] {case',': ++continuecase'}': ++return , nildefault:return , jsonwire.NewInvalidCharacterError(.buf[:], "after object value (expecting ',' or '}')") } }}// consumeArray consumes a single JSON array starting at d.buf[pos:].// It returns the new position in d.buf immediately after the array.func ( *decoderState) ( *jsonwire.ValueFlags, , int) ( int, error) {// Handle before start.ifuint() >= uint(len(.buf)) || .buf[] != '[' {panic("BUG: consumeArray must be called with a buffer that starts with '['") } elseif == maxNestingDepth+1 {return , errMaxDepth } ++// Handle after start. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } }if .buf[] == ']' { ++return , nil }varint64 ++for {// Handle before value. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } } , = .consumeValue(, , )if != nil {return , wrapWithArrayIndex(, ) }// Handle after value. += jsonwire.ConsumeWhitespace(.buf[:])if .needMore() {if , = .consumeWhitespace(); != nil {return , } }switch .buf[] {case',': ++ ++continuecase']': ++return , nildefault:return , jsonwire.NewInvalidCharacterError(.buf[:], "after array element (expecting ',' or ']')") } }}// InputOffset returns the current input byte offset. It gives the location// of the next byte immediately after the most recently returned token or value.// The number of bytes actually read from the underlying [io.Reader] may be more// than this offset due to internal buffering.func ( *Decoder) () int64 {return .s.previousOffsetEnd()}// UnreadBuffer returns the data remaining in the unread buffer,// which may contain zero or more bytes.// This is the data already consumed from the input [io.Reader],// but not yet read by a [Decoder.ReadToken] or [Decoder.ReadValue] call.// It may contain bytes that do not form valid JSON, since it has not yet// been validated according to the JSON grammar.// The exact amount of buffered data is an implementation detail// of the Decoder and may change over time.//// It is the caller's responsibility to concatenate this buffer with// the remainder of the input Reader to obtain the full sequence// of bytes after the last read JSON token or value.//// The returned buffer must not be mutated while Decoder continues to be used.// The buffer contents are valid until the next Peek, Read, or Skip call.func ( *Decoder) () []byte {return .s.unreadBuffer()}// StackDepth returns the depth of the state machine for JSON data// that has already been read.// Each level on the stack represents a nested JSON object or array.// It is incremented whenever a [BeginObject] or [BeginArray] token is encountered// and decremented whenever an [EndObject] or [EndArray] token is encountered.//// StackDepth returns 0 when not inside any object or array.// In particular, it returns 0 before any tokens have been read,// after any top-level value has been read, and between values// when decoding a stream of top-level values (e.g., NDJSON).// StackDepth returns 1 inside a top-level object or array,// 2 inside a nested object or array, and so on.//// For example, consider decoding the following JSON://// {"a": [1, 2], "b": {"c": 3}}//// While decoding, StackDepth would report the following://// - At the start, StackDepth reports 0.// - After decoding the outer '{', StackDepth reports 1.// - After decoding the inner '[', StackDepth reports 2.// - After decoding the inner ']', StackDepth reports 1.// - After decoding the outer '}', StackDepth reports 0.func ( *Decoder) () int {// NOTE: Keep in sync with Encoder.StackDepth.return .s.Tokens.Depth() - 1}// StackIndex returns information about the specified stack level.// It must be a number between 0 and [Decoder.StackDepth], inclusive.// For each level, it reports the kind://// - [KindInvalid] for a level of zero,// - [KindBeginObject] for a level representing a JSON object, and// - [KindBeginArray] for a level representing a JSON array.//// It also reports the length of that JSON object or array decoded so far.// Each name and value in a JSON object is counted separately,// so the effective number of members is half the length.// A complete JSON object must have an even length.func ( *Decoder) ( int) (Kind, int64) {// NOTE: Keep in sync with Encoder.StackIndex.switch := .s.Tokens.index(); {case > 0 && .isObject():return'{', .Length()case > 0 && .isArray():return'[', .Length()default:return0, .Length() }}// StackPointer returns a JSON Pointer (RFC 6901) to the most recently read value.func ( *Decoder) () Pointer {returnPointer(.s.AppendStackPointer(nil, -1))}func ( *decoderState) ( []byte, int) []byte { .Names.copyQuotedBuffer(.buf)return .state.appendStackPointer(, )}
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)