Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+59
-18
@@ -34,11 +34,11 @@ import (
|
||||
// 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 errors or state machine violations,
|
||||
// - 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 updated Decoder.prevStart and Decoder.prevEnd.
|
||||
// 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,
|
||||
@@ -71,7 +71,7 @@ import (
|
||||
// d.ReadValue() // {"k":"v"}
|
||||
// d.ReadToken() // }
|
||||
//
|
||||
// The above is one of many possible sequence of calls and
|
||||
// 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.
|
||||
@@ -80,7 +80,7 @@ type Decoder struct {
|
||||
}
|
||||
|
||||
// decoderState is the low-level state of Decoder.
|
||||
// It has exported fields and method for use by the "json" package.
|
||||
// It has exported fields and methods for use by the "json" package.
|
||||
type decoderState struct {
|
||||
state
|
||||
decodeBuffer
|
||||
@@ -126,7 +126,7 @@ func NewDecoder(r io.Reader, opts ...Options) *Decoder {
|
||||
}
|
||||
|
||||
// Reset resets a decoder such that it is reading afresh from r and
|
||||
// configured with the provided options. Reset must not be called on an
|
||||
// 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 (d *Decoder) Reset(r io.Reader, opts ...Options) {
|
||||
@@ -154,7 +154,7 @@ func (d *decoderState) reset(b []byte, r io.Reader, opts ...Options) {
|
||||
d.Struct = opts2
|
||||
}
|
||||
|
||||
// Options returns the options used to construct the encoder and
|
||||
// Options returns the options used to construct the decoder and
|
||||
// may additionally contain semantic options passed to a
|
||||
// [encoding/json/v2.UnmarshalDecode] call.
|
||||
//
|
||||
@@ -166,6 +166,8 @@ func (d *Decoder) Options() Options {
|
||||
return &d.s.Struct
|
||||
}
|
||||
|
||||
func (d *decoderState) options() *jsonopts.Struct { return &d.Struct }
|
||||
|
||||
var errBufferWriteAfterNext = errors.New("invalid bytes.Buffer.Write call after calling bytes.Buffer.Next")
|
||||
|
||||
// fetch reads at least 1 byte from the underlying io.Reader.
|
||||
@@ -193,7 +195,7 @@ func (d *decoderState) fetch() error {
|
||||
// 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 poor implementation of 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}
|
||||
}
|
||||
@@ -306,7 +308,7 @@ func (d *decodeBuffer) PreviousTokenOrValue() []byte {
|
||||
|
||||
// PeekKind retrieves the next token kind, but does not advance the read offset.
|
||||
//
|
||||
// It returns 0 if an error occurs. Any such error is cached until
|
||||
// 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 (d *Decoder) PeekKind() Kind {
|
||||
@@ -407,10 +409,11 @@ func (d *decoderState) checkDelim(delim byte, next Kind) error {
|
||||
}
|
||||
|
||||
// SkipValue is semantically equivalent to calling [Decoder.ReadValue] and discarding
|
||||
// the result except that memory is not wasted trying to hold the entire result.
|
||||
// the result, except that memory is not wasted trying to hold the entire result.
|
||||
func (d *Decoder) SkipValue() error {
|
||||
return d.s.SkipValue()
|
||||
}
|
||||
|
||||
func (d *decoderState) SkipValue() error {
|
||||
switch d.PeekKind() {
|
||||
case '{', '[':
|
||||
@@ -621,6 +624,7 @@ func (d *decoderState) ReadToken() (Token, error) {
|
||||
if !d.Flags.Get(jsonflags.AllowDuplicateNames) {
|
||||
d.Namespaces.push()
|
||||
}
|
||||
d.Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth
|
||||
pos += 1
|
||||
d.prevStart, d.prevEnd = pos, pos
|
||||
return BeginObject, nil
|
||||
@@ -641,6 +645,7 @@ func (d *decoderState) ReadToken() (Token, error) {
|
||||
if err = d.Tokens.pushArray(); err != nil {
|
||||
return Token{}, wrapSyntacticError(d, err, pos, +1)
|
||||
}
|
||||
d.Flags.Clear(jsonflags.TagFlags) // tags only apply to current depth
|
||||
pos += 1
|
||||
d.prevStart, d.prevEnd = pos, pos
|
||||
return BeginArray, nil
|
||||
@@ -792,6 +797,12 @@ func (d *decoderState) CheckNextValue(last bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AtEOF reports whether the decoder is at EOF.
|
||||
func (d *decoderState) AtEOF() bool {
|
||||
_, err := d.consumeWhitespace(d.prevEnd)
|
||||
return err == io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
// CheckEOF verifies that the input has no more data.
|
||||
func (d *decoderState) CheckEOF() error {
|
||||
return d.checkEOF(d.prevEnd)
|
||||
@@ -1121,24 +1132,54 @@ func (d *decoderState) consumeArray(flags *jsonwire.ValueFlags, pos, depth int)
|
||||
// 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 effects.
|
||||
// than this offset due to internal buffering.
|
||||
func (d *Decoder) InputOffset() int64 {
|
||||
return d.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 (d *Decoder) UnreadBuffer() []byte {
|
||||
return d.s.unreadBuffer()
|
||||
}
|
||||
|
||||
// StackDepth returns the depth of the state machine for read JSON data.
|
||||
// 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 an [BeginObject] or [BeginArray] token is encountered
|
||||
// It is incremented whenever a [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.
|
||||
//
|
||||
// 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 (d *Decoder) StackDepth() int {
|
||||
// NOTE: Keep in sync with Encoder.StackDepth.
|
||||
return d.s.Tokens.Depth() - 1
|
||||
@@ -1148,13 +1189,13 @@ func (d *Decoder) StackDepth() int {
|
||||
// It must be a number between 0 and [Decoder.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.
|
||||
// - [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.
|
||||
// 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 would be half the length.
|
||||
// so the effective number of members is half the length.
|
||||
// A complete JSON object must have an even length.
|
||||
func (d *Decoder) StackIndex(i int) (Kind, int64) {
|
||||
// NOTE: Keep in sync with Encoder.StackIndex.
|
||||
|
||||
Reference in new issue
Block a user