summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 21:48:38 -0700
committerLuke Shumaker <lukeshu@lukeshu.com>2023-02-10 21:48:38 -0700
commit95180a90db47990d32104ff7ab103e4862fd8426 (patch)
tree7733466fac856d93bfb6d6100fd703830a915567
parente9f3bdc767027d134a072e09f16bcccac75fa59f (diff)
parentddffd7b78d81f1b47b5829eb9ff0aa1887cc3b17 (diff)
Merge branch 'lukeshu/misc'
-rw-r--r--.golangci.yml3
-rw-r--r--README.md18
-rw-r--r--ReleaseNotes.md10
-rw-r--r--borrowed_misc.go43
-rw-r--r--common.go16
-rw-r--r--compat/json/README.md12
-rw-r--r--compat/json/borrowed_encode_test.go3
-rw-r--r--compat/json/borrowed_example_marshaling_test.go3
-rw-r--r--compat/json/borrowed_example_test.go7
-rw-r--r--compat/json/borrowed_example_text_marshaling_test.go3
-rw-r--r--compat/json/borrowed_fuzz_test.go5
-rw-r--r--compat/json/borrowed_stream_test.go5
-rw-r--r--compat/json/compat_test.go27
-rw-r--r--decode.go17
-rw-r--r--encode.go40
-rw-r--r--encode_string.go14
-rw-r--r--external.go48
-rw-r--r--internal/jsonstruct/struct.go2
-rw-r--r--internal/jsontest/jsontest.go14
19 files changed, 182 insertions, 108 deletions
diff --git a/.golangci.yml b/.golangci.yml
index 3675d1d..a235195 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -88,6 +88,9 @@ issues:
- path: "borrowed_.*_test\\.go"
linters: [gocritic]
text: "commentFormatting: put a space between `//` and comment text"
+ - path: "borrowed_.*_test\\.go"
+ linters: [gocritic]
+ text: "ifElseChain: rewrite if-else to switch statement"
- path: "internal/"
linters: [stylecheck]
text: "ST1000" # package doc comment
diff --git a/README.md b/README.md
index 108f3dc..4ef4038 100644
--- a/README.md
+++ b/README.md
@@ -141,17 +141,17 @@ These are streaming variants of the standard `json.Unmarshaler` and
<!-- packages -->
[`lowmemjson`]: https://pkg.go.dev/git.lukeshu.com/go/lowmemjson
[`lowmemjson/compat/json`]: https://pkg.go.dev/git.lukeshu.com/go/lowmemjson/compat/json
-[`encoding/json`]: https://pkg.go.dev/encoding/json@go1.18
+[`encoding/json`]: https://pkg.go.dev/encoding/json@go1.20
<!-- encoding/json symbols -->
-[`json.Marshaler`]: https://pkg.go.dev/encoding/json@go1.18#Marshaler
-[`json.Unmarshaler`]: https://pkg.go.dev/encoding/json@go1.18#Unmarshaler
-[`json.Marshal`]: https://pkg.go.dev/encoding/json@go1.18#Marshal
-[`json.Unmarshal`]: https://pkg.go.dev/encoding/json@go1.18#Unmarshal
-[`json.Compact`]: https://pkg.go.dev/encoding/json@go1.18#Compact
-[`json.HTMLEscape`]: https://pkg.go.dev/encoding/json@go1.18#HTMLEscape
-[`json.Indent`]: https://pkg.go.dev/encoding/json@go1.18#Indent
-[`json.Valid`]: https://pkg.go.dev/encoding/json@go1.18#Valid
+[`json.Marshaler`]: https://pkg.go.dev/encoding/json@go1.20#Marshaler
+[`json.Unmarshaler`]: https://pkg.go.dev/encoding/json@go1.20#Unmarshaler
+[`json.Marshal`]: https://pkg.go.dev/encoding/json@go1.20#Marshal
+[`json.Unmarshal`]: https://pkg.go.dev/encoding/json@go1.20#Unmarshal
+[`json.Compact`]: https://pkg.go.dev/encoding/json@go1.20#Compact
+[`json.HTMLEscape`]: https://pkg.go.dev/encoding/json@go1.20#HTMLEscape
+[`json.Indent`]: https://pkg.go.dev/encoding/json@go1.20#Indent
+[`json.Valid`]: https://pkg.go.dev/encoding/json@go1.20#Valid
<!-- lowmemjson symbols -->
[`lowmemjson.Encodable`]: https://pkg.go.dev/git.lukeshu.com/go/lowmemjson#Encodable
diff --git a/ReleaseNotes.md b/ReleaseNotes.md
index d1b5693..9974f0e 100644
--- a/ReleaseNotes.md
+++ b/ReleaseNotes.md
@@ -1,3 +1,13 @@
+# v0.3.6 (TBD)
+
+ Theme: TBD
+
+ User-facing changes:
+
+ - `Number` and `RawMessage` type aliases are now available, so that
+ a user of lowmemjson's native APIs does not need to import
+ `encoding/json` or compat/json in order to use them.
+
# v0.3.5 (2023-02-10)
Theme: Compatibility bugfixes
diff --git a/borrowed_misc.go b/borrowed_misc.go
index 59c49aa..52f4a12 100644
--- a/borrowed_misc.go
+++ b/borrowed_misc.go
@@ -7,7 +7,10 @@
package lowmemjson
import (
+ "io"
+ "math"
"reflect"
+ "strconv"
)
// isEmptyValue is borrowed from encode.go.
@@ -28,3 +31,43 @@ func isEmptyValue(v reflect.Value) bool {
}
return false
}
+
+// encodeFloat is lightly modified from
+// encode.go:floatEncoder.encode().
+func encodeFloat(w io.Writer, bits int, v reflect.Value) error {
+ var scratch [64]byte
+
+ f := v.Float()
+ if math.IsInf(f, 0) || math.IsNaN(f) {
+ return &EncodeValueError{Value: v, Str: strconv.FormatFloat(f, 'g', -1, bits)}
+ }
+
+ // Convert as if by ES6 number to string conversion.
+ // This matches most other JSON generators.
+ // See golang.org/issue/6384 and golang.org/issue/14135.
+ // Like fmt %g, but the exponent cutoffs are different
+ // and exponents themselves are not padded to two digits.
+ b := scratch[:0]
+ abs := math.Abs(f)
+ fmt := byte('f')
+ // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+ if abs != 0 {
+ if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
+ fmt = 'e'
+ }
+ }
+ b = strconv.AppendFloat(b, f, fmt, -1, bits)
+ if fmt == 'e' {
+ // clean up e-09 to e-9
+ n := len(b)
+ if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
+ b[n-2] = b[n-1]
+ b = b[:n-1]
+ }
+ }
+
+ if _, err := w.Write(b); err != nil {
+ return err
+ }
+ return nil
+}
diff --git a/common.go b/common.go
deleted file mode 100644
index 90156b9..0000000
--- a/common.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
-//
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package lowmemjson
-
-import (
- "encoding/json"
- "reflect"
-)
-
-var (
- numberType = reflect.TypeOf(json.Number(""))
- byteType = reflect.TypeOf(byte(0))
- byteSliceType = reflect.TypeOf(([]byte)(nil))
-)
diff --git a/compat/json/README.md b/compat/json/README.md
index ec8dbed..531b87e 100644
--- a/compat/json/README.md
+++ b/compat/json/README.md
@@ -50,11 +50,11 @@ Types that are deprecated in `encoding/json` are not mimiced here:
<!-- packages -->
[`lowmemjson`]: https://pkg.go.dev/git.lukeshu.com/go/lowmemjson
-[`encoding/json`]: https://pkg.go.dev/encoding/json@go1.18
+[`encoding/json`]: https://pkg.go.dev/encoding/json@go1.20
<!-- symbols -->
-[`Delim`]: https://pkg.go.dev/encoding/json@go1.18#Delim
-[`Token`]: https://pkg.go.dev/encoding/json@go1.18#Token
-[`Decoder.Token`]: https://pkg.go.dev/encoding/json@go1.18#Decoder.Token
-[`InvalidUTF8Error`]: https://pkg.go.dev/encoding/json@go1.18#InvalidUTF8Error
-[`UnmarshalFieldError`]: https://pkg.go.dev/encoding/json@go1.18#UnmarshalFieldError
+[`Delim`]: https://pkg.go.dev/encoding/json@go1.20#Delim
+[`Token`]: https://pkg.go.dev/encoding/json@go1.20#Token
+[`Decoder.Token`]: https://pkg.go.dev/encoding/json@go1.20#Decoder.Token
+[`InvalidUTF8Error`]: https://pkg.go.dev/encoding/json@go1.20#InvalidUTF8Error
+[`UnmarshalFieldError`]: https://pkg.go.dev/encoding/json@go1.20#UnmarshalFieldError
diff --git a/compat/json/borrowed_encode_test.go b/compat/json/borrowed_encode_test.go
index 999c694..d602934 100644
--- a/compat/json/borrowed_encode_test.go
+++ b/compat/json/borrowed_encode_test.go
@@ -10,7 +10,6 @@ import (
"bytes"
"encoding"
"fmt"
- "log"
"math"
"reflect"
"regexp"
@@ -1085,7 +1084,7 @@ func TestMarshalFloat(t *testing.T) {
s := fmt.Sprintf("%c%se%d", sign, digits[:i], exp)
f, err := strconv.ParseFloat(s, bits)
if err != nil {
- log.Fatal(err)
+ t.Fatal(err) // MODIFIED: changed from log.Fatal to t.Fatal
}
next := math.Nextafter
if bits == 32 {
diff --git a/compat/json/borrowed_example_marshaling_test.go b/compat/json/borrowed_example_marshaling_test.go
index 44a7c5d..e1af4df 100644
--- a/compat/json/borrowed_example_marshaling_test.go
+++ b/compat/json/borrowed_example_marshaling_test.go
@@ -7,10 +7,11 @@
package json_test
import (
- "encoding/json"
"fmt"
"log"
"strings"
+
+ "git.lukeshu.com/go/lowmemjson/compat/json"
)
type Animal int
diff --git a/compat/json/borrowed_example_test.go b/compat/json/borrowed_example_test.go
index fd984cd..5c612eb 100644
--- a/compat/json/borrowed_example_test.go
+++ b/compat/json/borrowed_example_test.go
@@ -8,12 +8,13 @@ package json_test
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"log"
"os"
"strings"
+
+ "git.lukeshu.com/go/lowmemjson/compat/json"
)
func ExampleMarshal() {
@@ -85,6 +86,7 @@ func ExampleDecoder() {
// Ed: Go fmt yourself!
}
+/* // MODIFIED: we don't have tokens
// This example uses a Decoder to decode a stream of distinct JSON values.
func ExampleDecoder_Token() {
const jsonStream = `
@@ -121,7 +123,9 @@ func ExampleDecoder_Token() {
// float64: 1.234
// json.Delim: }
}
+*/ // MODIFIED: we don't have tokens
+/* // MODIFIED: we don't have tokens
// This example uses a Decoder to decode a streaming array of JSON objects.
func ExampleDecoder_Decode_stream() {
const jsonStream = `
@@ -173,6 +177,7 @@ func ExampleDecoder_Decode_stream() {
// Ed: Go fmt yourself!
// json.Delim: ]
}
+*/ // MODIFIED: we don't have tokens
// This example uses RawMessage to delay parsing part of a JSON message.
func ExampleRawMessage_unmarshal() {
diff --git a/compat/json/borrowed_example_text_marshaling_test.go b/compat/json/borrowed_example_text_marshaling_test.go
index 3bfcd34..821851c 100644
--- a/compat/json/borrowed_example_text_marshaling_test.go
+++ b/compat/json/borrowed_example_text_marshaling_test.go
@@ -7,10 +7,11 @@
package json_test
import (
- "encoding/json"
"fmt"
"log"
"strings"
+
+ "git.lukeshu.com/go/lowmemjson/compat/json"
)
type Size int
diff --git a/compat/json/borrowed_fuzz_test.go b/compat/json/borrowed_fuzz_test.go
index 6a0b0d1..a909d75 100644
--- a/compat/json/borrowed_fuzz_test.go
+++ b/compat/json/borrowed_fuzz_test.go
@@ -7,6 +7,8 @@
package json
import (
+ "bytes"
+ "io"
"testing"
)
@@ -50,8 +52,8 @@ func FuzzUnmarshalJSON(f *testing.F) {
})
}
-/* // MODIFIED: we don't do tokens
func FuzzDecoderToken(f *testing.F) {
+ f.Skip("we don't have tokens") // MODIFIED: added
f.Add([]byte(`{
"object": {
"slice": [
@@ -82,4 +84,3 @@ func FuzzDecoderToken(f *testing.F) {
}
})
}
-*/ // MODIFIED: we don't do tokens
diff --git a/compat/json/borrowed_stream_test.go b/compat/json/borrowed_stream_test.go
index d90898b..d50898a 100644
--- a/compat/json/borrowed_stream_test.go
+++ b/compat/json/borrowed_stream_test.go
@@ -363,8 +363,6 @@ func TestBlocking(t *testing.T) {
}
}
-//nolint:dupword // False positive, this is commented-out code, not a real comment. // MODIFIED: added nolint declaration
-/* // MODIFIED: we don't have tokens
type tokenStreamCase struct {
json string
expTokens []any
@@ -446,6 +444,8 @@ var tokenStreamCases = []tokenStreamCase{
}
func TestDecodeInStream(t *testing.T) {
+ t.Parallel() // MODIFIED: added
+ t.Skip("we don't have tokens") // MODIFIED: added
for ci, tcase := range tokenStreamCases {
dec := NewDecoder(strings.NewReader(tcase.json))
@@ -479,7 +479,6 @@ func TestDecodeInStream(t *testing.T) {
}
}
}
-*/ // MODIFIED: we don't have tokens
// Test from golang.org/issue/11893
func TestHTTPDecoding(t *testing.T) {
diff --git a/compat/json/compat_test.go b/compat/json/compat_test.go
index 203594f..07c75bc 100644
--- a/compat/json/compat_test.go
+++ b/compat/json/compat_test.go
@@ -6,12 +6,14 @@ package json
import (
"bytes"
+ "encoding/json"
"io"
+ _ "unsafe"
"git.lukeshu.com/go/lowmemjson"
+ "git.lukeshu.com/go/lowmemjson/internal/fastio"
"git.lukeshu.com/go/lowmemjson/internal/jsonparse"
"git.lukeshu.com/go/lowmemjson/internal/jsonstruct"
- "git.lukeshu.com/go/lowmemjson/internal/jsontest"
)
var (
@@ -56,10 +58,29 @@ type encodeState struct {
bytes.Buffer
}
+//go:linkname encodeStringFromString git.lukeshu.com/go/lowmemjson.encodeStringFromString
+func encodeStringFromString(w fastio.AllWriter, escaper lowmemjson.BackslashEscaper, str string) error
+
+//go:linkname encodeStringFromBytes git.lukeshu.com/go/lowmemjson.encodeStringFromBytes
+func encodeStringFromBytes(w fastio.AllWriter, escaper lowmemjson.BackslashEscaper, str []byte) error
+
func (es *encodeState) string(str string, _ bool) {
- jsontest.EncodeStringFromString(&es.Buffer, str)
+ if err := encodeStringFromString(&es.Buffer, nil, str); err != nil {
+ panic(err)
+ }
}
func (es *encodeState) stringBytes(str []byte, _ bool) {
- jsontest.EncodeStringFromBytes(&es.Buffer, str)
+ if err := encodeStringFromBytes(&es.Buffer, nil, str); err != nil {
+ panic(err)
+ }
+}
+
+type (
+ Token = json.Token
+ Delim = json.Delim
+)
+
+func (dec *Decoder) Token() (Token, error) {
+ panic("not implemented")
}
diff --git a/decode.go b/decode.go
index 487bce4..645f8de 100644
--- a/decode.go
+++ b/decode.go
@@ -14,7 +14,6 @@ package lowmemjson
import (
"bytes"
"encoding"
- "encoding/json"
"fmt"
"io"
"reflect"
@@ -232,7 +231,7 @@ func (dec *Decoder) DecodeThenEOF(ptr any) (err error) {
// json.Unmarshaler interface it also checks for the Decodable
// interface.
//
-// [documentation for encoding/json.Unmarshal]: https://pkg.go.dev/encoding/json@go1.18#Unmarshal
+// [documentation for encoding/json.Unmarshal]: https://pkg.go.dev/encoding/json@go1.20#Unmarshal
func (dec *Decoder) Decode(ptr any) (err error) {
ptrVal := reflect.ValueOf(ptr)
if ptrVal.Kind() != reflect.Pointer || ptrVal.IsNil() || !ptrVal.Elem().CanSet() {
@@ -357,14 +356,6 @@ func (dec *Decoder) limitingScanner() io.RuneScanner {
// decoder main ////////////////////////////////////////////////////////////////////////////////////
-var (
- rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil))
- decodableType = reflect.TypeOf((*Decodable)(nil)).Elem()
- jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
- textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
- float64Type = reflect.TypeOf(float64(0))
-)
-
var kind2bits = map[reflect.Kind]int{
reflect.Int: int(32 << (^uint(0) >> 63)),
reflect.Int8: 8,
@@ -393,7 +384,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
t := dec.peekRuneType()
var buf bytes.Buffer
dec.scan(&buf)
- if err := val.Addr().Interface().(*json.RawMessage).UnmarshalJSON(buf.Bytes()); err != nil {
+ if err := val.Addr().Interface().(*RawMessage).UnmarshalJSON(buf.Bytes()); err != nil {
dec.panicType(t.JSONType(), reflect.PointerTo(typ), err)
}
case val.CanAddr() && reflect.PointerTo(typ).Implements(decodableType):
@@ -410,7 +401,7 @@ func (dec *Decoder) decode(val reflect.Value, nullOK bool) {
t := dec.peekRuneType()
var buf bytes.Buffer
dec.scan(&buf)
- obj := val.Addr().Interface().(json.Unmarshaler)
+ obj := val.Addr().Interface().(jsonUnmarshaler)
if err := obj.UnmarshalJSON(buf.Bytes()); err != nil {
dec.panicType(t.JSONType(), reflect.PointerTo(typ), err)
}
@@ -826,7 +817,7 @@ func (dec *Decoder) decodeAny() any {
case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
var buf strings.Builder
dec.scan(&buf)
- num := json.Number(buf.String())
+ num := Number(buf.String())
if dec.useNumber {
return num
}
diff --git a/encode.go b/encode.go
index 2d16891..b6541cd 100644
--- a/encode.go
+++ b/encode.go
@@ -8,7 +8,6 @@ import (
"bytes"
"encoding"
"encoding/base64"
- "encoding/json"
"fmt"
"io"
"reflect"
@@ -78,7 +77,7 @@ func NewEncoder(w io.Writer) *Encoder {
// may write partial output, whereas encodin/json would not have
// written anything.
//
-// [documentation for encoding/json.Marshal]: https://pkg.go.dev/encoding/json@go1.18#Marshal
+// [documentation for encoding/json.Marshal]: https://pkg.go.dev/encoding/json@go1.20#Marshal
func (enc *Encoder) Encode(obj any) (err error) {
if enc.isRoot {
enc.w.par.Reset()
@@ -96,12 +95,6 @@ func discardInt(_ int, err error) error {
return err
}
-var (
- encodableType = reflect.TypeOf((*Encodable)(nil)).Elem()
- jsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
- textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
-)
-
const startDetectingCyclesAfter = 1000
func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote bool, cycleDepth uint, cycleSeen map[any]struct{}) error {
@@ -145,7 +138,7 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote boo
if val.Kind() == reflect.Pointer && val.IsNil() {
return discardInt(w.WriteString("null"))
}
- obj, ok := val.Interface().(json.Marshaler)
+ obj, ok := val.Interface().(jsonMarshaler)
if !ok {
return discardInt(w.WriteString("null"))
}
@@ -246,13 +239,27 @@ func encode(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, quote boo
return err
}
}
- case reflect.Float32, reflect.Float64:
+ case reflect.Float32:
if quote {
if err := w.WriteByte('"'); err != nil {
return err
}
}
- if err := encodeTODO(w, val); err != nil {
+ if err := encodeFloat(w, 32, val); err != nil {
+ return err
+ }
+ if quote {
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ case reflect.Float64:
+ if quote {
+ if err := w.WriteByte('"'); err != nil {
+ return err
+ }
+ }
+ if err := encodeFloat(w, 64, val); err != nil {
return err
}
if quote {
@@ -522,14 +529,3 @@ func encodeArray(w *ReEncoder, val reflect.Value, escaper BackslashEscaper, cycl
}
return nil
}
-
-func encodeTODO(w io.Writer, val reflect.Value) error {
- bs, err := json.Marshal(val.Interface())
- if err != nil {
- return err
- }
- if _, err := w.Write(bs); err != nil {
- return err
- }
- return nil
-}
diff --git a/encode_string.go b/encode_string.go
index a5d6633..328b07a 100644
--- a/encode_string.go
+++ b/encode_string.go
@@ -10,7 +10,6 @@ import (
"git.lukeshu.com/go/lowmemjson/internal/fastio"
"git.lukeshu.com/go/lowmemjson/internal/jsonparse"
- "git.lukeshu.com/go/lowmemjson/internal/jsontest"
)
func writeStringUnicodeEscape(w io.Writer, c rune) (int, error) {
@@ -116,16 +115,3 @@ func encodeStringFromBytes(w fastio.AllWriter, escaper BackslashEscaper, str []b
}
return nil
}
-
-func init() {
- jsontest.EncodeStringFromString = func(w io.Writer, s string) {
- if err := encodeStringFromString(fastio.NewAllWriter(w), nil, s); err != nil {
- panic(err)
- }
- }
- jsontest.EncodeStringFromBytes = func(w io.Writer, s []byte) {
- if err := encodeStringFromBytes(fastio.NewAllWriter(w), nil, s); err != nil {
- panic(err)
- }
- }
-}
diff --git a/external.go b/external.go
new file mode 100644
index 0000000..c8a1f68
--- /dev/null
+++ b/external.go
@@ -0,0 +1,48 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package lowmemjson
+
+import (
+ "encoding"
+ "encoding/json"
+ "reflect"
+)
+
+// A Number represents a JSON number value. It is represented as a
+// string containing the raw JSON text; it is useful for preserving
+// number values with perfect fidelity, but isn't so useful for use as
+// a number value in a Go program.
+type Number = json.Number
+
+// A RawMessage is a raw encoded JSON value. This saves time when
+// encoding or decoding, but does mean that the full text must be
+// buffered when decoding.
+type RawMessage = json.RawMessage
+
+type (
+ jsonMarshaler = json.Marshaler
+ jsonUnmarshaler = json.Unmarshaler
+)
+
+var (
+ // common types.
+ numberType = reflect.TypeOf(Number(""))
+ byteType = reflect.TypeOf(byte(0))
+ byteSliceType = reflect.TypeOf(([]byte)(nil))
+
+ // encodable/marshaler types.
+ encodableType = reflect.TypeOf((*Encodable)(nil)).Elem()
+ jsonMarshalerType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
+ textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
+
+ // decodable/unmarshaler types.
+ decodableType = reflect.TypeOf((*Decodable)(nil)).Elem()
+ jsonUnmarshalerType = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
+ textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
+
+ // other types used by Decoder.
+ rawMessagePtrType = reflect.TypeOf((*json.RawMessage)(nil))
+ float64Type = reflect.TypeOf(float64(0))
+)
diff --git a/internal/jsonstruct/struct.go b/internal/jsonstruct/struct.go
index 16c45de..20e82ca 100644
--- a/internal/jsonstruct/struct.go
+++ b/internal/jsonstruct/struct.go
@@ -63,7 +63,7 @@ func indexStructReal(typ reflect.Type) StructIndex {
ret.ByName[name] = len(ret.ByPos)
ret.ByPos = append(ret.ByPos, _field)
default:
- // To quote the encoding/json docs (version 1.18.4):
+ // To quote the encoding/json docs (version 1.20):
//
// If there are multiple fields at the same level, and that level is the
// least nested (and would therefore be the nesting level selected by the
diff --git a/internal/jsontest/jsontest.go b/internal/jsontest/jsontest.go
deleted file mode 100644
index fbc775d..0000000
--- a/internal/jsontest/jsontest.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
-//
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package jsontest
-
-import (
- "io"
-)
-
-var (
- EncodeStringFromBytes func(io.Writer, []byte)
- EncodeStringFromString func(io.Writer, string)
-)