diff --git a/ring_buffer.go b/ring_buffer.go index 1d31c28..b46e126 100644 --- a/ring_buffer.go +++ b/ring_buffer.go @@ -553,6 +553,12 @@ func (r *RingBuffer) ReadFrom(rd io.Reader) (n int64, err error) { continue } if rerr != nil && rerr != io.EOF { + // Keep the bytes that came with the error. + if nr > 0 { + r.w = (startW + nr) % r.size + r.isFull = r.r == r.w + n += int64(nr) + } err = r.setErr(rerr, true) r.mu.Unlock() break diff --git a/ring_buffer_test.go b/ring_buffer_test.go index dc64bd5..7a5c194 100644 --- a/ring_buffer_test.go +++ b/ring_buffer_test.go @@ -973,6 +973,7 @@ func (e *errormock) Read(p []byte) (n int, err error) { case len(p) > e.rleft: n = e.rleft + err = e.rerr default: n = len(p) @@ -1031,6 +1032,22 @@ func TestRingBuffer_ReadFrom_Error(t *testing.T) { } } +func TestRingBuffer_ReadFrom_ErrorKeepsData(t *testing.T) { + rb := New(16).SetBlocking(true) + tester := &errormock{rerr: io.ErrUnexpectedEOF, rleft: 5} + + copied, err := rb.ReadFrom(tester) + if err != io.ErrUnexpectedEOF { + t.Errorf("expect io.ErrUnexpectedEOF but got %v", err) + } + if copied != 5 { + t.Errorf("expect 5 bytes copied but got %d", copied) + } + if got := rb.Length(); got != 5 { + t.Errorf("expect 5 bytes buffered but got %d", got) + } +} + func TestRingBuffer_WriteTo_Error(t *testing.T) { const bufsize = 4 << 10