aboutsummaryrefslogtreecommitdiff
path: root/internal/zlib/reader.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/zlib/reader.go')
-rw-r--r--internal/zlib/reader.go50
1 files changed, 40 insertions, 10 deletions
diff --git a/internal/zlib/reader.go b/internal/zlib/reader.go
index 5d6dcd88..e4babb9e 100644
--- a/internal/zlib/reader.go
+++ b/internal/zlib/reader.go
@@ -63,6 +63,7 @@ var (
var readerPool = sync.Pool{
New: func() any {
r := new(reader)
+
return r
},
}
@@ -89,14 +90,17 @@ func NewReader(r io.Reader) (io.ReadCloser, error) {
// If the compressed data refers to a different dictionary, NewReaderDict returns [ErrDictionary].
func NewReaderDict(r io.Reader, dict []byte) (io.ReadCloser, error) {
v := readerPool.Get()
+
z, ok := v.(*reader)
if !ok {
panic("zlib: pool returned unexpected type")
}
+
err := z.Reset(r, dict)
if err != nil {
return nil, err
}
+
return z, nil
}
@@ -106,30 +110,40 @@ func (z *reader) Read(p []byte) (int, error) {
}
var n int
+
n, z.err = z.decompressor.Read(p)
- if _, err := z.digest.Write(p[0:n]); err != nil {
+
+ _, err := z.digest.Write(p[0:n])
+ if err != nil {
z.err = err
+
return n, z.err
}
+
if !errors.Is(z.err, io.EOF) {
// In the normal case we return here.
return n, z.err
}
// Finished file; check checksum.
- if _, err := io.ReadFull(z.r, z.scratch[0:4]); err != nil {
- if err == io.EOF {
+ _, err = io.ReadFull(z.r, z.scratch[0:4])
+ if err != nil {
+ if errors.Is(err, io.EOF) {
err = io.ErrUnexpectedEOF
}
+
z.err = err
+
return n, z.err
}
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
checksum := binary.BigEndian.Uint32(z.scratch[:4])
if checksum != z.digest.Sum32() {
z.err = ErrChecksum
+
return n, z.err
}
+
return n, io.EOF
}
@@ -140,12 +154,14 @@ func (z *reader) Close() error {
if z.err != nil && !errors.Is(z.err, io.EOF) {
return z.err
}
+
z.err = z.decompressor.Close()
if z.err != nil {
return z.err
}
readerPool.Put(z)
+
return nil
}
@@ -163,13 +179,17 @@ func (z *reader) Reset(r io.Reader, dict []byte) error {
if errors.Is(z.err, io.EOF) {
z.err = io.ErrUnexpectedEOF
}
+
return z.err
}
+
h := binary.BigEndian.Uint16(z.scratch[:2])
if (z.scratch[0]&0x0f != zlibDeflate) || (z.scratch[0]>>4 > zlibMaxWindow) || (h%31 != 0) {
z.err = ErrHeader
+
return z.err
}
+
haveDict := z.scratch[1]&0x20 != 0
if haveDict {
_, z.err = io.ReadFull(z.r, z.scratch[0:4])
@@ -177,31 +197,41 @@ func (z *reader) Reset(r io.Reader, dict []byte) error {
if errors.Is(z.err, io.EOF) {
z.err = io.ErrUnexpectedEOF
}
+
return z.err
}
+
checksum := binary.BigEndian.Uint32(z.scratch[:4])
if checksum != adler32.Checksum(dict) {
z.err = ErrDictionary
+
return z.err
}
}
- if z.decompressor == nil {
- if haveDict {
- z.decompressor = flate.NewReaderDict(z.r, dict)
- } else {
- z.decompressor = flate.NewReader(z.r)
- }
- } else {
+ if z.decompressor != nil {
resetter, ok := z.decompressor.(flate.Resetter)
if !ok {
panic("zlib: pooled decompressor does not implement flate.Resetter")
}
+
z.err = resetter.Reset(z.r, dict)
if z.err != nil {
return z.err
}
+
+ z.digest = adler32.New()
+
+ return nil
+ }
+
+ if haveDict {
+ z.decompressor = flate.NewReaderDict(z.r, dict)
+ } else {
+ z.decompressor = flate.NewReader(z.r)
}
+
z.digest = adler32.New()
+
return nil
}