|
|
@@ -14,15 +14,22 @@ import (
|
|
|
|
|
|
var (
|
|
|
flateWriterPool = sync.Pool{}
|
|
|
+ flateReaderPool = sync.Pool{}
|
|
|
)
|
|
|
|
|
|
-func decompressNoContextTakeover(r io.Reader) io.Reader {
|
|
|
+func decompressNoContextTakeover(r io.Reader) io.ReadCloser {
|
|
|
const tail =
|
|
|
// Add four bytes as specified in RFC
|
|
|
"\x00\x00\xff\xff" +
|
|
|
// Add final block to squelch unexpected EOF error from flate reader.
|
|
|
"\x01\x00\x00\xff\xff"
|
|
|
- return flate.NewReader(io.MultiReader(r, strings.NewReader(tail)))
|
|
|
+
|
|
|
+ i := flateReaderPool.Get()
|
|
|
+ if i == nil {
|
|
|
+ i = flate.NewReader(nil)
|
|
|
+ }
|
|
|
+ i.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
|
|
|
+ return &flateReadWrapper{i.(io.ReadCloser)}
|
|
|
}
|
|
|
|
|
|
func compressNoContextTakeover(w io.WriteCloser) (io.WriteCloser, error) {
|
|
|
@@ -36,7 +43,7 @@ func compressNoContextTakeover(w io.WriteCloser) (io.WriteCloser, error) {
|
|
|
fw = i.(*flate.Writer)
|
|
|
fw.Reset(tw)
|
|
|
}
|
|
|
- return &flateWrapper{fw: fw, tw: tw}, err
|
|
|
+ return &flateWriteWrapper{fw: fw, tw: tw}, err
|
|
|
}
|
|
|
|
|
|
// truncWriter is an io.Writer that writes all but the last four bytes of the
|
|
|
@@ -75,19 +82,19 @@ func (w *truncWriter) Write(p []byte) (int, error) {
|
|
|
return n + nn, err
|
|
|
}
|
|
|
|
|
|
-type flateWrapper struct {
|
|
|
+type flateWriteWrapper struct {
|
|
|
fw *flate.Writer
|
|
|
tw *truncWriter
|
|
|
}
|
|
|
|
|
|
-func (w *flateWrapper) Write(p []byte) (int, error) {
|
|
|
+func (w *flateWriteWrapper) Write(p []byte) (int, error) {
|
|
|
if w.fw == nil {
|
|
|
return 0, errWriteClosed
|
|
|
}
|
|
|
return w.fw.Write(p)
|
|
|
}
|
|
|
|
|
|
-func (w *flateWrapper) Close() error {
|
|
|
+func (w *flateWriteWrapper) Close() error {
|
|
|
if w.fw == nil {
|
|
|
return errWriteClosed
|
|
|
}
|
|
|
@@ -103,3 +110,31 @@ func (w *flateWrapper) Close() error {
|
|
|
}
|
|
|
return err2
|
|
|
}
|
|
|
+
|
|
|
+type flateReadWrapper struct {
|
|
|
+ fr io.ReadCloser
|
|
|
+}
|
|
|
+
|
|
|
+func (r *flateReadWrapper) Read(p []byte) (int, error) {
|
|
|
+ if r.fr == nil {
|
|
|
+ return 0, io.ErrClosedPipe
|
|
|
+ }
|
|
|
+ n, err := r.fr.Read(p)
|
|
|
+ if err == io.EOF {
|
|
|
+ // Preemptively place the reader back in the pool. This helps with
|
|
|
+ // scenarios where the application does not call NextReader() soon after
|
|
|
+ // this final read.
|
|
|
+ r.Close()
|
|
|
+ }
|
|
|
+ return n, err
|
|
|
+}
|
|
|
+
|
|
|
+func (r *flateReadWrapper) Close() error {
|
|
|
+ if r.fr == nil {
|
|
|
+ return io.ErrClosedPipe
|
|
|
+ }
|
|
|
+ err := r.fr.Close()
|
|
|
+ flateReaderPool.Put(r.fr)
|
|
|
+ r.fr = nil
|
|
|
+ return err
|
|
|
+}
|