- Updated test files to collect events first and sort them by their CreatedAt timestamp before processing, ensuring events are handled in chronological order. - Removed redundant error checks for scanner errors after event processing. - Enhanced clarity and maintainability of event handling in tests across multiple files, including export, fetch, and query tests. - Adjusted expected index counts in tests to reflect changes in event structure and processing logic.
232 lines
6.8 KiB
Go
232 lines
6.8 KiB
Go
// Copyright 2010 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 json
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
|
|
"next.orly.dev/pkg/json/jsontext"
|
|
jsonv2 "next.orly.dev/pkg/json/v2"
|
|
)
|
|
|
|
// A Decoder reads and decodes JSON values from an input stream.
|
|
type Decoder struct {
|
|
dec *jsontext.Decoder
|
|
opts jsonv2.Options
|
|
err error
|
|
}
|
|
|
|
// NewDecoder returns a new decoder that reads from r.
|
|
//
|
|
// The decoder introduces its own buffering and may
|
|
// read data from r beyond the JSON values requested.
|
|
func NewDecoder(r io.Reader) *Decoder {
|
|
// Hide bytes.Buffer from jsontext since it implements optimizations that
|
|
// also limits certain ways it could be used. For example, one cannot write
|
|
// to the bytes.Buffer while it is in use by jsontext.Decoder.
|
|
if _, ok := r.(*bytes.Buffer); ok {
|
|
r = struct{ io.Reader }{r}
|
|
}
|
|
|
|
dec := new(Decoder)
|
|
dec.opts = DefaultOptionsV1()
|
|
dec.dec = jsontext.NewDecoder(r, dec.opts)
|
|
return dec
|
|
}
|
|
|
|
// UseNumber causes the Decoder to unmarshal a number into an
|
|
// interface value as a [Number] instead of as a float64.
|
|
func (dec *Decoder) UseNumber() {
|
|
if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); !useNumber {
|
|
dec.opts = jsonv2.JoinOptions(dec.opts, unmarshalAnyWithRawNumber(true))
|
|
}
|
|
}
|
|
|
|
// DisallowUnknownFields causes the Decoder to return an error when the destination
|
|
// is a struct and the input contains object keys which do not match any
|
|
// non-ignored, exported fields in the destination.
|
|
func (dec *Decoder) DisallowUnknownFields() {
|
|
if reject, _ := jsonv2.GetOption(dec.opts, jsonv2.RejectUnknownMembers); !reject {
|
|
dec.opts = jsonv2.JoinOptions(dec.opts, jsonv2.RejectUnknownMembers(true))
|
|
}
|
|
}
|
|
|
|
// Decode reads the next JSON-encoded value from its
|
|
// input and stores it in the value pointed to by v.
|
|
//
|
|
// See the documentation for [Unmarshal] for details about
|
|
// the conversion of JSON into a Go value.
|
|
func (dec *Decoder) Decode(v any) error {
|
|
if dec.err != nil {
|
|
return dec.err
|
|
}
|
|
b, err := dec.dec.ReadValue()
|
|
if err != nil {
|
|
dec.err = transformSyntacticError(err)
|
|
if dec.err.Error() == errUnexpectedEnd.Error() {
|
|
// NOTE: Decode has always been inconsistent with Unmarshal
|
|
// with regard to the exact error value for truncated input.
|
|
dec.err = io.ErrUnexpectedEOF
|
|
}
|
|
return dec.err
|
|
}
|
|
return jsonv2.Unmarshal(b, v, dec.opts)
|
|
}
|
|
|
|
// Buffered returns a reader of the data remaining in the Decoder's
|
|
// buffer. The reader is valid until the next call to [Decoder.Decode].
|
|
func (dec *Decoder) Buffered() io.Reader {
|
|
return bytes.NewReader(dec.dec.UnreadBuffer())
|
|
}
|
|
|
|
// An Encoder writes JSON values to an output stream.
|
|
type Encoder struct {
|
|
w io.Writer
|
|
opts jsonv2.Options
|
|
err error
|
|
|
|
buf bytes.Buffer
|
|
indentBuf bytes.Buffer
|
|
|
|
indentPrefix string
|
|
indentValue string
|
|
}
|
|
|
|
// NewEncoder returns a new encoder that writes to w.
|
|
func NewEncoder(w io.Writer) *Encoder {
|
|
enc := new(Encoder)
|
|
enc.w = w
|
|
enc.opts = DefaultOptionsV1()
|
|
return enc
|
|
}
|
|
|
|
// Encode writes the JSON encoding of v to the stream,
|
|
// followed by a newline character.
|
|
//
|
|
// See the documentation for [Marshal] for details about the
|
|
// conversion of Go values to JSON.
|
|
func (enc *Encoder) Encode(v any) error {
|
|
if enc.err != nil {
|
|
return enc.err
|
|
}
|
|
|
|
buf := &enc.buf
|
|
buf.Reset()
|
|
if err := jsonv2.MarshalWrite(buf, v, enc.opts); err != nil {
|
|
return err
|
|
}
|
|
if len(enc.indentPrefix)+len(enc.indentValue) > 0 {
|
|
enc.indentBuf.Reset()
|
|
if err := Indent(&enc.indentBuf, buf.Bytes(), enc.indentPrefix, enc.indentValue); err != nil {
|
|
return err
|
|
}
|
|
buf = &enc.indentBuf
|
|
}
|
|
buf.WriteByte('\n')
|
|
|
|
if _, err := enc.w.Write(buf.Bytes()); err != nil {
|
|
enc.err = err
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetIndent instructs the encoder to format each subsequent encoded
|
|
// value as if indented by the package-level function Indent(dst, src, prefix, indent).
|
|
// Calling SetIndent("", "") disables indentation.
|
|
func (enc *Encoder) SetIndent(prefix, indent string) {
|
|
enc.indentPrefix = prefix
|
|
enc.indentValue = indent
|
|
}
|
|
|
|
// SetEscapeHTML specifies whether problematic HTML characters
|
|
// should be escaped inside JSON quoted strings.
|
|
// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
|
|
// to avoid certain safety problems that can arise when embedding JSON in HTML.
|
|
//
|
|
// In non-HTML settings where the escaping interferes with the readability
|
|
// of the output, SetEscapeHTML(false) disables this behavior.
|
|
func (enc *Encoder) SetEscapeHTML(on bool) {
|
|
if escape, _ := jsonv2.GetOption(enc.opts, jsontext.EscapeForHTML); escape != on {
|
|
enc.opts = jsonv2.JoinOptions(enc.opts, jsontext.EscapeForHTML(on))
|
|
}
|
|
}
|
|
|
|
// RawMessage is a raw encoded JSON value.
|
|
// It implements [Marshaler] and [Unmarshaler] and can
|
|
// be used to delay JSON decoding or precompute a JSON encoding.
|
|
type RawMessage = jsontext.Value
|
|
|
|
// A Token holds a value of one of these types:
|
|
//
|
|
// - [Delim], for the four JSON delimiters [ ] { }
|
|
// - bool, for JSON booleans
|
|
// - float64, for JSON numbers
|
|
// - [Number], for JSON numbers
|
|
// - string, for JSON string literals
|
|
// - nil, for JSON null
|
|
type Token any
|
|
|
|
// A Delim is a JSON array or object delimiter, one of [ ] { or }.
|
|
type Delim rune
|
|
|
|
func (d Delim) String() string {
|
|
return string(d)
|
|
}
|
|
|
|
// Token returns the next JSON token in the input stream.
|
|
// At the end of the input stream, Token returns nil, [io.EOF].
|
|
//
|
|
// Token guarantees that the delimiters [ ] { } it returns are
|
|
// properly nested and matched: if Token encounters an unexpected
|
|
// delimiter in the input, it will return an error.
|
|
//
|
|
// The input stream consists of basic JSON values—bool, string,
|
|
// number, and null—along with delimiters [ ] { } of type [Delim]
|
|
// to mark the start and end of arrays and objects.
|
|
// Commas and colons are elided.
|
|
func (dec *Decoder) Token() (Token, error) {
|
|
tok, err := dec.dec.ReadToken()
|
|
if err != nil {
|
|
return nil, transformSyntacticError(err)
|
|
}
|
|
switch k := tok.Kind(); k {
|
|
case 'n':
|
|
return nil, nil
|
|
case 'f':
|
|
return false, nil
|
|
case 't':
|
|
return true, nil
|
|
case '"':
|
|
return tok.String(), nil
|
|
case '0':
|
|
if useNumber, _ := jsonv2.GetOption(dec.opts, unmarshalAnyWithRawNumber); useNumber {
|
|
return Number(tok.String()), nil
|
|
}
|
|
return tok.Float(), nil
|
|
case '{', '}', '[', ']':
|
|
return Delim(k), nil
|
|
default:
|
|
panic("unreachable")
|
|
}
|
|
}
|
|
|
|
// More reports whether there is another element in the
|
|
// current array or object being parsed.
|
|
func (dec *Decoder) More() bool {
|
|
k := dec.dec.PeekKind()
|
|
return k > 0 && k != ']' && k != '}'
|
|
}
|
|
|
|
// InputOffset returns the input stream byte offset of the current decoder position.
|
|
// The offset gives the location of the end of the most recently returned token
|
|
// and the beginning of the next token.
|
|
func (dec *Decoder) InputOffset() int64 {
|
|
return dec.dec.InputOffset()
|
|
}
|