summaryrefslogtreecommitdiff
path: root/internal
diff options
context:
space:
mode:
Diffstat (limited to 'internal')
-rw-r--r--internal/base64dec/base64.go (renamed from internal/base64.go)8
-rw-r--r--internal/base64dec/base64_test.go (renamed from internal/base64_test.go)2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/06e2c9db80a08b67fad7f1a4606dc7419750995a57828aa25ea57fe7099d5c032
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/24f53a36f8832fec65cac0aa0f3b43ec1c904414fa6d38f6fc288b0bbd69588a2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae22
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/356e28f5914a0f16f3cef81330f1d92060be4d694a93dedd654bf48743a7d2bd2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed42
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/60c81ee499a7f1e151b66b08f0a4ff81edd7cb53d00dce8ee0eaf316839960262
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/731951fe84fa6f3a7f6ee8adaa585d4f6a01f359a04737e51ffc70f16f480b9b2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/7d6367ba84cd18550920b5202cd1269174416ce32769c7f59376e76b7dd3129c2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/9201a772731543760326638b8915f80863feab0ba0108183b3093934bdc0420c2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/92f75f690317ace34aeaae3fe39f5f2ff9830777253ff371c5ef6f403a0f8f0f2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/93d6f7bc0d93f998c7b7fe654ff46010d6fa76f0a142c3523c42454f8ad10b072
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a7450fd77fc7c53cc5bd136874415dddfff5c586e662f21420caa7a94131a56a2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a95d2a0f87501a643d54218d2ad8112204672cc1fb30be297853616788208a5c2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/beed435aa2fee4819eab217543561dfd8001d4a44f53ceb664aaba86cebfaf212
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b42
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e92
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/cc90a4a40ae9b3beac70baf6d7821a5a6f3a90cabb033575790be917235936802
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/ec72f669d648d8d9b9f75a3b303897c59b11e4bfb7622f25ff251a92f182bc2a2
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab32
-rw-r--r--internal/base64dec/testdata/fuzz/FuzzBase64Decoder/fd67efb09d433a1351a201281dbf6568628b4135c35c811dd9bce97620a75d432
-rw-r--r--internal/fastio/allwriter.go (renamed from internal/allwriter.go)2
-rw-r--r--internal/jsonparse/hex.go (renamed from internal/hex.go)2
-rw-r--r--internal/jsonparse/parse.go (renamed from internal/parse.go)2
-rw-r--r--internal/jsonparse/parse_test.go (renamed from internal/parse_test.go)2
-rw-r--r--internal/jsonstruct/borrowed_misc.go30
-rw-r--r--internal/jsonstruct/borrowed_tags.go (renamed from internal/borrowed_tags.go)2
-rw-r--r--internal/jsonstruct/struct.go209
-rw-r--r--internal/jsontest/jsontest.go (renamed from internal/encode.go)2
-rw-r--r--internal/tags.go7
33 files changed, 295 insertions, 17 deletions
diff --git a/internal/base64.go b/internal/base64dec/base64.go
index 291a229..dcb4b1c 100644
--- a/internal/base64.go
+++ b/internal/base64dec/base64.go
@@ -2,12 +2,14 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package base64dec
import (
"encoding/base64"
"io"
"strings"
+
+ "git.lukeshu.com/go/lowmemjson/internal/fastio"
)
type base64Decoder struct {
@@ -21,7 +23,7 @@ type base64Decoder struct {
func NewBase64Decoder(w io.Writer) interface {
io.WriteCloser
- RuneWriter
+ fastio.RuneWriter
} {
return &base64Decoder{
dst: w,
@@ -116,7 +118,7 @@ func (dec *base64Decoder) Write(dat []byte) (int, error) {
}
func (dec *base64Decoder) WriteRune(r rune) (int, error) {
- return WriteRune(dec, r)
+ return fastio.WriteRune(dec, r)
}
func (dec *base64Decoder) Close() error {
diff --git a/internal/base64_test.go b/internal/base64dec/base64_test.go
index f18bcd7..cb3063d 100644
--- a/internal/base64_test.go
+++ b/internal/base64dec/base64_test.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package base64dec
import (
"bytes"
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/06e2c9db80a08b67fad7f1a4606dc7419750995a57828aa25ea57fe7099d5c03 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/06e2c9db80a08b67fad7f1a4606dc7419750995a57828aa25ea57fe7099d5c03
new file mode 100644
index 0000000..c3774e7
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/06e2c9db80a08b67fad7f1a4606dc7419750995a57828aa25ea57fe7099d5c03
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("0000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/24f53a36f8832fec65cac0aa0f3b43ec1c904414fa6d38f6fc288b0bbd69588a b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/24f53a36f8832fec65cac0aa0f3b43ec1c904414fa6d38f6fc288b0bbd69588a
new file mode 100644
index 0000000..4c861db
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/24f53a36f8832fec65cac0aa0f3b43ec1c904414fa6d38f6fc288b0bbd69588a
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2
new file mode 100644
index 0000000..3d32e14
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/2d49311ef22319f70a3590a86b406b9f2565987a4a3b6d7660ddc308b5b2fae2
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/356e28f5914a0f16f3cef81330f1d92060be4d694a93dedd654bf48743a7d2bd b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/356e28f5914a0f16f3cef81330f1d92060be4d694a93dedd654bf48743a7d2bd
new file mode 100644
index 0000000..d08ef92
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/356e28f5914a0f16f3cef81330f1d92060be4d694a93dedd654bf48743a7d2bd
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4
new file mode 100644
index 0000000..a96f559
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/582528ddfad69eb57775199a43e0f9fd5c94bba343ce7bb6724d4ebafe311ed4
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("0")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/60c81ee499a7f1e151b66b08f0a4ff81edd7cb53d00dce8ee0eaf31683996026 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/60c81ee499a7f1e151b66b08f0a4ff81edd7cb53d00dce8ee0eaf31683996026
new file mode 100644
index 0000000..87c024d
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/60c81ee499a7f1e151b66b08f0a4ff81edd7cb53d00dce8ee0eaf31683996026
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("0000000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d
new file mode 100644
index 0000000..959401e
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/66498f377f38b53eebe1ceaa4a53e4de01a04efc02ac9cfda60f9815f80e9b9d
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/731951fe84fa6f3a7f6ee8adaa585d4f6a01f359a04737e51ffc70f16f480b9b b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/731951fe84fa6f3a7f6ee8adaa585d4f6a01f359a04737e51ffc70f16f480b9b
new file mode 100644
index 0000000..bd1ae59
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/731951fe84fa6f3a7f6ee8adaa585d4f6a01f359a04737e51ffc70f16f480b9b
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/7d6367ba84cd18550920b5202cd1269174416ce32769c7f59376e76b7dd3129c b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/7d6367ba84cd18550920b5202cd1269174416ce32769c7f59376e76b7dd3129c
new file mode 100644
index 0000000..09e0ad2
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/7d6367ba84cd18550920b5202cd1269174416ce32769c7f59376e76b7dd3129c
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c
new file mode 100644
index 0000000..e8000f3
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/8727b16d337d7b8187433233f3a90099024e580a6ba319ea2bf539880c50bd7c
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/9201a772731543760326638b8915f80863feab0ba0108183b3093934bdc0420c b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/9201a772731543760326638b8915f80863feab0ba0108183b3093934bdc0420c
new file mode 100644
index 0000000..aac6b7d
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/9201a772731543760326638b8915f80863feab0ba0108183b3093934bdc0420c
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/92f75f690317ace34aeaae3fe39f5f2ff9830777253ff371c5ef6f403a0f8f0f b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/92f75f690317ace34aeaae3fe39f5f2ff9830777253ff371c5ef6f403a0f8f0f
new file mode 100644
index 0000000..f3bf6d9
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/92f75f690317ace34aeaae3fe39f5f2ff9830777253ff371c5ef6f403a0f8f0f
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/93d6f7bc0d93f998c7b7fe654ff46010d6fa76f0a142c3523c42454f8ad10b07 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/93d6f7bc0d93f998c7b7fe654ff46010d6fa76f0a142c3523c42454f8ad10b07
new file mode 100644
index 0000000..2e7f462
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/93d6f7bc0d93f998c7b7fe654ff46010d6fa76f0a142c3523c42454f8ad10b07
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a7450fd77fc7c53cc5bd136874415dddfff5c586e662f21420caa7a94131a56a b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a7450fd77fc7c53cc5bd136874415dddfff5c586e662f21420caa7a94131a56a
new file mode 100644
index 0000000..c541f52
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a7450fd77fc7c53cc5bd136874415dddfff5c586e662f21420caa7a94131a56a
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a95d2a0f87501a643d54218d2ad8112204672cc1fb30be297853616788208a5c b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a95d2a0f87501a643d54218d2ad8112204672cc1fb30be297853616788208a5c
new file mode 100644
index 0000000..5d56f29
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/a95d2a0f87501a643d54218d2ad8112204672cc1fb30be297853616788208a5c
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/beed435aa2fee4819eab217543561dfd8001d4a44f53ceb664aaba86cebfaf21 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/beed435aa2fee4819eab217543561dfd8001d4a44f53ceb664aaba86cebfaf21
new file mode 100644
index 0000000..4b4d59f
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/beed435aa2fee4819eab217543561dfd8001d4a44f53ceb664aaba86cebfaf21
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4
new file mode 100644
index 0000000..ef9f9d4
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/c2501043394e49f2477408be5ef9389790e33ed1886073dec445d4cf05bcd4b4
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9
new file mode 100644
index 0000000..67322c7
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/caf81e9797b19c76c1fc4dbf537d4d81f389524539f402d13aa01f93a65ac7e9
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/cc90a4a40ae9b3beac70baf6d7821a5a6f3a90cabb033575790be91723593680 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/cc90a4a40ae9b3beac70baf6d7821a5a6f3a90cabb033575790be91723593680
new file mode 100644
index 0000000..f195330
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/cc90a4a40ae9b3beac70baf6d7821a5a6f3a90cabb033575790be91723593680
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\x04000000000000\r00000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/ec72f669d648d8d9b9f75a3b303897c59b11e4bfb7622f25ff251a92f182bc2a b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/ec72f669d648d8d9b9f75a3b303897c59b11e4bfb7622f25ff251a92f182bc2a
new file mode 100644
index 0000000..5b0d392
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/ec72f669d648d8d9b9f75a3b303897c59b11e4bfb7622f25ff251a92f182bc2a
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("0000000000000000000000000000000000000000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3
new file mode 100644
index 0000000..a389d3c
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/f34630c44c11bb13d27531927c5c1e65d159b70f39cd161da0dba348c1221ab3
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("00000")
diff --git a/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/fd67efb09d433a1351a201281dbf6568628b4135c35c811dd9bce97620a75d43 b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/fd67efb09d433a1351a201281dbf6568628b4135c35c811dd9bce97620a75d43
new file mode 100644
index 0000000..17d10b2
--- /dev/null
+++ b/internal/base64dec/testdata/fuzz/FuzzBase64Decoder/fd67efb09d433a1351a201281dbf6568628b4135c35c811dd9bce97620a75d43
@@ -0,0 +1,2 @@
+go test fuzz v1
+[]byte("000000000000")
diff --git a/internal/allwriter.go b/internal/fastio/allwriter.go
index 187aa8e..9de8fdc 100644
--- a/internal/allwriter.go
+++ b/internal/fastio/allwriter.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package fastio
import (
"io"
diff --git a/internal/hex.go b/internal/jsonparse/hex.go
index 62a818f..3ed5f01 100644
--- a/internal/hex.go
+++ b/internal/jsonparse/hex.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package jsonparse
const Hex = "0123456789abcdef"
diff --git a/internal/parse.go b/internal/jsonparse/parse.go
index 36db4a9..7d97be0 100644
--- a/internal/parse.go
+++ b/internal/jsonparse/parse.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package jsonparse
import (
"errors"
diff --git a/internal/parse_test.go b/internal/jsonparse/parse_test.go
index 34977fb..e531daf 100644
--- a/internal/parse_test.go
+++ b/internal/jsonparse/parse_test.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package jsonparse
import (
"testing"
diff --git a/internal/jsonstruct/borrowed_misc.go b/internal/jsonstruct/borrowed_misc.go
new file mode 100644
index 0000000..3b4181e
--- /dev/null
+++ b/internal/jsonstruct/borrowed_misc.go
@@ -0,0 +1,30 @@
+// 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.
+//
+// SPDX-License-Identifier: BSD-3-Clause
+
+package jsonstruct
+
+import (
+ "strings"
+ "unicode"
+)
+
+// isValidTag is borrowed from encode.go.
+func isValidTag(s string) bool {
+ if s == "" {
+ return false
+ }
+ for _, c := range s {
+ switch {
+ case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
+ // Backslash and quote chars are reserved, but
+ // otherwise any punctuation chars are allowed
+ // in a tag name.
+ case !unicode.IsLetter(c) && !unicode.IsDigit(c):
+ return false
+ }
+ }
+ return true
+}
diff --git a/internal/borrowed_tags.go b/internal/jsonstruct/borrowed_tags.go
index 6eaf5da..f2ef71c 100644
--- a/internal/borrowed_tags.go
+++ b/internal/jsonstruct/borrowed_tags.go
@@ -4,7 +4,7 @@
//
// SPDX-License-Identifier: BSD-3-Clause
-package internal // MODIFIED: changed package name
+package jsonstruct // MODIFIED: changed package name
import (
"strings"
diff --git a/internal/jsonstruct/struct.go b/internal/jsonstruct/struct.go
new file mode 100644
index 0000000..16c45de
--- /dev/null
+++ b/internal/jsonstruct/struct.go
@@ -0,0 +1,209 @@
+// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
+//
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package jsonstruct
+
+import (
+ "reflect"
+
+ "git.lukeshu.com/go/typedsync"
+)
+
+var ParseTag = parseTag
+
+type StructField struct {
+ Name string
+ Path []int
+ Tagged bool
+ OmitEmpty bool
+ Quote bool
+}
+
+// A StructIndex is used by Decoder.Decode() and Encoder.Encode() when
+// decoding-to or encoding-from a struct.
+type StructIndex struct {
+ ByPos []StructField
+ ByName map[string]int
+}
+
+var structIndexCache typedsync.CacheMap[reflect.Type, StructIndex]
+
+// IndexStruct takes a struct Type, and indexes its fields for use by
+// Decoder.Decode() and Encoder.Encode(). indexStruct caches its
+// results.
+func IndexStruct(typ reflect.Type) StructIndex {
+ ret, _ := structIndexCache.LoadOrCompute(typ, indexStructReal)
+ return ret
+}
+
+func ClearCache() {
+ structIndexCache = typedsync.CacheMap[reflect.Type, StructIndex]{}
+}
+
+// indexStructReal is like indexStruct, but is the real indexer,
+// bypassing the cache.
+func indexStructReal(typ reflect.Type) StructIndex {
+ var byPos []StructField
+ byName := make(map[string][]int)
+
+ indexStructInner(typ, &byPos, byName, nil, map[reflect.Type]struct{}{})
+
+ ret := StructIndex{
+ ByName: make(map[string]int),
+ }
+
+ for curPos, _field := range byPos {
+ name := _field.Name
+ fieldPoss := byName[name]
+ switch len(fieldPoss) {
+ case 0:
+ // do nothing
+ case 1:
+ ret.ByName[name] = len(ret.ByPos)
+ ret.ByPos = append(ret.ByPos, _field)
+ default:
+ // To quote the encoding/json docs (version 1.18.4):
+ //
+ // 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
+ // usual Go rules), the following extra rules apply:
+ //
+ // 1) Of those fields, if any are JSON-tagged, only tagged fields are
+ // considered, even if there are multiple untagged fields that would
+ // otherwise conflict.
+ //
+ // 2) If there is exactly one field (tagged or not according to the first
+ // rule), that is selected.
+ //
+ // 3) Otherwise there are multiple fields, and all are ignored; no error
+ // occurs.
+ leastLevel := len(byPos[fieldPoss[0]].Path)
+ for _, fieldPos := range fieldPoss[1:] {
+ field := byPos[fieldPos]
+ if len(field.Path) < leastLevel {
+ leastLevel = len(field.Path)
+ }
+ }
+ var numUntagged, numTagged int
+ var untaggedPos, taggedPos int
+ for _, fieldPos := range fieldPoss {
+ field := byPos[fieldPos]
+ if len(field.Path) != leastLevel {
+ continue
+ }
+ if field.Tagged {
+ numTagged++
+ taggedPos = fieldPos
+ if numTagged > 1 {
+ break // optimization
+ }
+ } else {
+ numUntagged++
+ untaggedPos = fieldPos
+ }
+ }
+ switch numTagged {
+ case 0:
+ switch numUntagged {
+ case 0:
+ // do nothing
+ case 1:
+ if curPos == untaggedPos {
+ ret.ByName[name] = len(ret.ByPos)
+ ret.ByPos = append(ret.ByPos, byPos[curPos])
+ }
+ }
+ case 1:
+ if curPos == taggedPos {
+ ret.ByName[name] = len(ret.ByPos)
+ ret.ByPos = append(ret.ByPos, byPos[curPos])
+ }
+ }
+ }
+ }
+
+ return ret
+}
+
+// indexStructInner crawls the struct `typ`, storing information on
+// all struct fields found in to `byPos` and `byName`. If `typ`
+// contains other structs as fields, indexStructInner will recurse and
+// call itself; keeping track of stack information with `stackPath`
+// (which identifies where we are in the parent struct) and
+// `stackSeen` (which is used for detecting loops).
+func indexStructInner(typ reflect.Type, byPos *[]StructField, byName map[string][]int, stackPath []int, stackSeen map[reflect.Type]struct{}) {
+ if _, ok := stackSeen[typ]; ok {
+ return
+ }
+ stackSeen[typ] = struct{}{}
+ defer delete(stackSeen, typ)
+
+ n := typ.NumField()
+ for i := 0; i < n; i++ {
+ stackPath := append(stackPath, i)
+
+ fTyp := typ.Field(i)
+ var embed bool
+ if fTyp.Anonymous {
+ t := fTyp.Type
+ if t.Kind() == reflect.Pointer {
+ t = t.Elem()
+ }
+ if !fTyp.IsExported() && t.Kind() != reflect.Struct {
+ continue
+ }
+ embed = t.Kind() == reflect.Struct
+ } else if !fTyp.IsExported() {
+ continue
+ }
+ tag := fTyp.Tag.Get("json")
+ if tag == "-" {
+ continue
+ }
+ tagName, opts := parseTag(tag)
+ name := tagName
+ if !isValidTag(name) {
+ name = ""
+ }
+ if name == "" {
+ name = fTyp.Name
+ }
+
+ if embed && tagName == "" {
+ t := fTyp.Type
+ if t.Kind() == reflect.Pointer {
+ t = t.Elem()
+ }
+ indexStructInner(t, byPos, byName, stackPath, stackSeen)
+ } else {
+ byName[name] = append(byName[name], len(*byPos))
+ *byPos = append(*byPos, StructField{
+ Name: name,
+ Path: append([]int(nil), stackPath...),
+ Tagged: tagName != "",
+ OmitEmpty: opts.Contains("omitempty"),
+ Quote: opts.Contains("string") && isQuotable(fTyp.Type),
+ })
+ }
+ }
+}
+
+// isQuotable returns whether a type is eligible for `json:,string`
+// quoting.
+func isQuotable(typ reflect.Type) bool {
+ for typ.Kind() == reflect.Pointer {
+ typ = typ.Elem()
+ }
+ switch typ.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
+ reflect.Uintptr,
+ reflect.Float32, reflect.Float64,
+ reflect.String:
+ return true
+ default:
+ return false
+ }
+}
diff --git a/internal/encode.go b/internal/jsontest/jsontest.go
index 8aae673..fbc775d 100644
--- a/internal/encode.go
+++ b/internal/jsontest/jsontest.go
@@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: GPL-2.0-or-later
-package internal
+package jsontest
import (
"io"
diff --git a/internal/tags.go b/internal/tags.go
deleted file mode 100644
index bdf1f72..0000000
--- a/internal/tags.go
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) 2022-2023 Luke Shumaker <lukeshu@lukeshu.com>
-//
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package internal
-
-var ParseTag = parseTag