aboutsummaryrefslogtreecommitdiff
path: root/internal/zlib
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-04 08:26:56 +0800
committerGravatar Runxi Yu2026-03-04 08:59:53 +0800
commitab7501be34032fb9e5c48726a68ae90a917af9eb (patch)
tree20d005647569befea8133e953c3270e8fd2a2a5b /internal/zlib
parent*: gofumpt (diff)
signatureNo signature
*: Lint
Diffstat (limited to 'internal/zlib')
-rw-r--r--internal/zlib/reader.go50
-rw-r--r--internal/zlib/writer.go39
2 files changed, 76 insertions, 13 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
}
diff --git a/internal/zlib/writer.go b/internal/zlib/writer.go
index 75a8ec1d..bfc52889 100644
--- a/internal/zlib/writer.go
+++ b/internal/zlib/writer.go
@@ -52,6 +52,7 @@ var writerPool = sync.Pool{
// Writes may be buffered and not flushed until Close.
func NewWriter(w io.Writer) *Writer {
z, _ := NewWriterLevelDict(w, DefaultCompression, nil)
+
return z
}
@@ -74,7 +75,9 @@ func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
if level < HuffmanOnly || level > BestCompression {
return nil, fmt.Errorf("zlib: invalid compression level: %d", level)
}
+
v := writerPool.Get()
+
z, ok := v.(*Writer)
if !ok {
panic("zlib: pool returned unexpected type")
@@ -86,6 +89,7 @@ func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
if !reuseCompressor {
z.compressor = nil
}
+
if z.digest != nil {
z.digest.Reset()
}
@@ -100,6 +104,7 @@ func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error) {
if z.compressor != nil {
z.compressor.Reset(w)
}
+
return z, nil
}
@@ -112,9 +117,11 @@ func (z *Writer) Reset(w io.Writer) {
if z.compressor != nil {
z.compressor.Reset(w)
}
+
if z.digest != nil {
z.digest.Reset()
}
+
z.err = nil
z.scratch = [4]byte{}
z.wroteHeader = false
@@ -127,21 +134,29 @@ func (z *Writer) Write(p []byte) (n int, err error) {
if !z.wroteHeader {
z.err = z.writeHeader()
}
+
if z.err != nil {
return 0, z.err
}
+
if len(p) == 0 {
return 0, nil
}
+
n, err = z.compressor.Write(p)
if err != nil {
z.err = err
+
return n, err
}
- if _, err = z.digest.Write(p); err != nil {
+
+ _, err = z.digest.Write(p)
+ if err != nil {
z.err = err
+
return 0, z.err
}
+
return n, err
}
@@ -150,10 +165,13 @@ func (z *Writer) Flush() error {
if !z.wroteHeader {
z.err = z.writeHeader()
}
+
if z.err != nil {
return z.err
}
+
z.err = z.compressor.Flush()
+
return z.err
}
@@ -163,22 +181,27 @@ func (z *Writer) Close() error {
if !z.wroteHeader {
z.err = z.writeHeader()
}
+
if z.err != nil {
return z.err
}
+
z.err = z.compressor.Close()
if z.err != nil {
return z.err
}
+
checksum := z.digest.Sum32()
// ZLIB (RFC 1950) is big-endian, unlike GZIP (RFC 1952).
binary.BigEndian.PutUint32(z.scratch[:], checksum)
+
_, z.err = z.w.Write(z.scratch[0:4])
if z.err != nil {
return z.err
}
writerPool.Put(z)
+
return nil
}
@@ -205,20 +228,28 @@ func (z *Writer) writeHeader() (err error) {
default:
panic("unreachable")
}
+
if z.dict != nil {
z.scratch[1] |= 1 << 5
}
+
z.scratch[1] += uint8(31 - binary.BigEndian.Uint16(z.scratch[:2])%31) //#nosec G115
- if _, err = z.w.Write(z.scratch[0:2]); err != nil {
+
+ _, err = z.w.Write(z.scratch[0:2])
+ if err != nil {
return err
}
+
if z.dict != nil {
// The next four bytes are the Adler-32 checksum of the dictionary.
binary.BigEndian.PutUint32(z.scratch[:], adler32.Checksum(z.dict))
- if _, err = z.w.Write(z.scratch[0:4]); err != nil {
+
+ _, err = z.w.Write(z.scratch[0:4])
+ if err != nil {
return err
}
}
+
if z.compressor == nil {
// Initialize deflater unless the Writer is being reused
// after a Reset call.
@@ -226,7 +257,9 @@ func (z *Writer) writeHeader() (err error) {
if err != nil {
return err
}
+
z.digest = adler32.New()
}
+
return nil
}