From c25137b6d7d5945ae5cde2349a002d84c50d0e59 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Tue, 7 Feb 2023 13:24:02 -0700 Subject: decode: Fix decoding an actively growing file --- ReleaseNotes.md | 11 +++++++++++ decode.go | 8 +------- decode_scan.go | 2 ++ decode_test.go | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 5d85254..f71967c 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -1,3 +1,14 @@ +# v0.3.5 (TBD) + + Theme: TBD + + User-facing changes: + + - Decoder: Fixes a bug where if an EOF is encountered, the reader + is appended to, then another Decode is attempted, that EOF + poisons future Decodes. This is something that `encoding/json` + supports. + # v0.3.4 (2023-02-05) Theme: Fix compilation with Go 1.20 diff --git a/decode.go b/decode.go index 60b530f..8638148 100644 --- a/decode.go +++ b/decode.go @@ -90,7 +90,6 @@ type Decoder struct { useNumber bool // state - err error posStack []int64 structStack []decodeStackItem } @@ -240,18 +239,13 @@ func (dec *Decoder) Decode(ptr any) (err error) { } } - if dec.err != nil { - return dec.err - } - dec.io.Reset() dec.io.PushReadBarrier() defer func() { if r := recover(); r != nil { if de, ok := r.(decodeError); ok { pub := DecodeError(de) - dec.err = &pub - err = dec.err + err = &pub } else { panic(r) } diff --git a/decode_scan.go b/decode_scan.go index e233caf..521c5c4 100644 --- a/decode_scan.go +++ b/decode_scan.go @@ -45,6 +45,8 @@ func (sc *runeTypeScanner) Reset() { } // tell it to use that rType and rErr _ = sc.UnreadRune() // we set it up to always succeed + } else { + sc.initialized = false } } diff --git a/decode_test.go b/decode_test.go index 73ce903..456f363 100644 --- a/decode_test.go +++ b/decode_test.go @@ -5,6 +5,7 @@ package lowmemjson import ( + "bytes" "io" "strings" "testing" @@ -34,3 +35,16 @@ func TestDecodeObject(t *testing.T) { }) assert.ErrorContains(t, err, "did not consume entire") } + +func TestDecodeGrowing(t *testing.T) { + t.Parallel() + var buf bytes.Buffer + dec := NewDecoder(&buf) + var x any + assert.ErrorIs(t, dec.Decode(&x), io.EOF) + buf.WriteString("1\n") + assert.NoError(t, dec.Decode(&x)) + buf.WriteString("1\n") + assert.NoError(t, dec.Decode(&x)) + assert.ErrorIs(t, dec.Decode(&x), io.EOF) +} -- cgit v1.2.3-2-g168b