summaryrefslogtreecommitdiff
path: root/compat/json/compat.go
diff options
context:
space:
mode:
Diffstat (limited to 'compat/json/compat.go')
-rw-r--r--compat/json/compat.go33
1 files changed, 29 insertions, 4 deletions
diff --git a/compat/json/compat.go b/compat/json/compat.go
index c2d47c0..6f13fbb 100644
--- a/compat/json/compat.go
+++ b/compat/json/compat.go
@@ -329,7 +329,10 @@ func Unmarshal(data []byte, ptr any) error {
}
type teeRuneScanner struct {
- src io.RuneScanner
+ src interface {
+ io.RuneScanner
+ io.ByteScanner
+ }
dst *bytes.Buffer
lastSize int
}
@@ -337,11 +340,14 @@ type teeRuneScanner struct {
func (tee *teeRuneScanner) ReadRune() (r rune, size int, err error) {
r, size, err = tee.src.ReadRune()
if err == nil {
- if _, err := tee.dst.WriteRune(r); err != nil {
- return 0, 0, err
+ if r == utf8.RuneError && size == 1 {
+ _ = tee.src.UnreadRune()
+ b, _ := tee.src.ReadByte()
+ _ = tee.dst.WriteByte(b)
+ } else {
+ _, _ = tee.dst.WriteRune(r)
}
}
-
tee.lastSize = size
return
}
@@ -356,6 +362,25 @@ func (tee *teeRuneScanner) UnreadRune() error {
return nil
}
+func (tee *teeRuneScanner) ReadByte() (b byte, err error) {
+ b, err = tee.src.ReadByte()
+ if err == nil {
+ _ = tee.dst.WriteByte(b)
+ tee.lastSize = 1
+ }
+ return
+}
+
+func (tee *teeRuneScanner) UnreadByte() error {
+ if tee.lastSize != 1 {
+ return lowmemjson.ErrInvalidUnreadRune
+ }
+ _ = tee.src.UnreadByte()
+ tee.dst.Truncate(tee.dst.Len() - tee.lastSize)
+ tee.lastSize = 0
+ return nil
+}
+
type Decoder struct {
validatorBuf *bufio.Reader
validator *lowmemjson.Decoder