Skip to content

Commit dfaf538

Browse files
authored
fix: Handle small reads in branch converters (#144)
* fix: Handle reads into small slices Handle the case for `Read(p)` where `len(p)` is smaller than the minimum length required by the branch converter. * test: Make use of `iotest.OneByteReader()` This now exposes a bug in all of the branch converters. * fix: Handle small reads in branch converters Add missing benchmarks also.
1 parent f654743 commit dfaf538

File tree

3 files changed

+37
-5
lines changed

3 files changed

+37
-5
lines changed

internal/bra/bra.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,11 @@ func max(x, y int) int {
1212

1313
return y
1414
}
15+
16+
func min(x, y int) int {
17+
if x < y {
18+
return x
19+
}
20+
21+
return y
22+
}

internal/bra/reader.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
type readCloser struct {
1010
rc io.ReadCloser
1111
buf bytes.Buffer
12+
n int
1213
conv converter
1314
}
1415

@@ -30,13 +31,19 @@ func (rc *readCloser) Read(p []byte) (int, error) {
3031
if !errors.Is(err, io.EOF) {
3132
return 0, err
3233
}
33-
}
3434

35-
if n := rc.conv.Convert(rc.buf.Bytes(), false); n > 0 {
36-
return rc.buf.Read(p[:n])
35+
if rc.buf.Len() < rc.conv.Size() {
36+
rc.n = rc.buf.Len()
37+
}
3738
}
3839

39-
return rc.buf.Read(p)
40+
rc.n += rc.conv.Convert(rc.buf.Bytes()[rc.n:], false)
41+
42+
n, err := rc.buf.Read(p[:min(rc.n, len(p))])
43+
44+
rc.n -= n
45+
46+
return n, err
4047
}
4148

4249
func newReader(readers []io.ReadCloser, conv converter) (io.ReadCloser, error) {

reader_test.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"path/filepath"
99
"testing"
1010
"testing/fstest"
11+
"testing/iotest"
1112

1213
"github.com/bodgit/sevenzip"
1314
"github.com/bodgit/sevenzip/internal/util"
@@ -28,7 +29,7 @@ func readArchive(t *testing.T, r *sevenzip.ReadCloser) {
2829

2930
h.Reset()
3031

31-
if _, err := io.Copy(h, rc); err != nil {
32+
if _, err := io.Copy(h, iotest.OneByteReader(rc)); err != nil {
3233
t.Fatal(err)
3334
}
3435

@@ -332,3 +333,19 @@ func BenchmarkBrotli(b *testing.B) {
332333
func BenchmarkZstandard(b *testing.B) {
333334
benchmarkArchive(b, "zstd.7z")
334335
}
336+
337+
func BenchmarkBCJ(b *testing.B) {
338+
benchmarkArchive(b, "bcj.7z")
339+
}
340+
341+
func BenchmarkPPC(b *testing.B) {
342+
benchmarkArchive(b, "ppc.7z")
343+
}
344+
345+
func BenchmarkARM(b *testing.B) {
346+
benchmarkArchive(b, "arm.7z")
347+
}
348+
349+
func BenchmarkSPARC(b *testing.B) {
350+
benchmarkArchive(b, "sparc.7z")
351+
}

0 commit comments

Comments
 (0)