diff options
Diffstat (limited to 'compat/json/compat.go')
-rw-r--r-- | compat/json/compat.go | 33 |
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 |